1use core::{
10 num::NonZeroU64,
11 {
12 array,
13 iter::zip,
14 ops::{Add, Div, Mul, Neg, Sub},
15 },
16};
17
18use crate::{
19 addrs::{AddrVec, DataAddr, ElemAddr, MemAddr, ModuleAddr, TableAddr},
20 assert_validated::UnwrapValidatedExt,
21 core::{
22 indices::{DataIdx, FuncIdx, GlobalIdx, LabelIdx, LocalIdx, TableIdx, TypeIdx},
23 reader::{
24 types::{memarg::MemArg, BlockType},
25 WasmReader,
26 },
27 sidetable::Sidetable,
28 },
29 instances::{DataInst, ElemInst, FuncInst, MemInst, ModuleInst, TableInst},
30 resumable::Resumable,
31 store::HaltExecutionError,
32 unreachable_validated,
33 value::{self, Ref, F32, F64},
34 value_stack::Stack,
35 RefType, RuntimeError, TrapError, ValType, Value,
36};
37
38use crate::execution::config::Config;
39
40use super::{little_endian::LittleEndianBytes, store::Store};
41
42pub(super) fn run<T: Config>(
47 resumable: &mut Resumable,
48 store: &mut Store<T>,
49) -> Result<Option<NonZeroU64>, RuntimeError> {
50 let stack = &mut resumable.stack;
51 let mut current_func_addr = resumable.current_func_addr;
52 let pc = resumable.pc;
53 let mut stp = resumable.stp;
54 let func_inst = store.functions.get(current_func_addr);
55 let FuncInst::WasmFunc(wasm_func_inst) = &func_inst else {
56 unreachable!(
57 "the interpreter loop shall only be executed with native wasm functions as root call"
58 );
59 };
60 let mut current_module = wasm_func_inst.module_addr;
61
62 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(NonZeroU64::new($cost-*fuel));
93 }
94 }
95 }
96 }
97
98 let first_instr_byte = wasm.read_u8().unwrap_validated();
99
100 #[cfg(debug_assertions)]
101 trace!(
102 "Executing instruction {}",
103 opcode_byte_to_str(first_instr_byte)
104 );
105
106 match first_instr_byte {
107 NOP => {
108 decrement_fuel!(T::get_flat_cost(NOP));
109 trace!("Instruction: NOP");
110 }
111 END => {
112 if wasm.pc != current_function_end_marker {
115 continue;
116 }
117
118 let Some((maybe_return_func_addr, maybe_return_address, maybe_return_stp)) =
119 stack.pop_call_frame()
120 else {
121 break;
123 };
124 trace!("end of function reached, returning to previous call frame");
128 current_func_addr = maybe_return_func_addr;
129 let FuncInst::WasmFunc(current_wasm_func_inst) =
130 store.functions.get(current_func_addr)
131 else {
132 unreachable!("function addresses on the stack always correspond to native wasm functions")
133 };
134 current_module = current_wasm_func_inst.module_addr;
135 wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
136 wasm.pc = maybe_return_address;
137 stp = maybe_return_stp;
138
139 current_sidetable = &store.modules.get(current_module).sidetable;
140
141 current_function_end_marker = current_wasm_func_inst.code_expr.from()
142 + current_wasm_func_inst.code_expr.len();
143
144 trace!("Instruction: END");
145 }
146 IF => {
147 decrement_fuel!(T::get_flat_cost(IF));
148 wasm.read_var_u32().unwrap_validated();
149
150 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
151
152 if test_val != 0 {
153 stp += 1;
154 } else {
155 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
156 }
157 trace!("Instruction: IF");
158 }
159 ELSE => {
160 decrement_fuel!(T::get_flat_cost(ELSE));
161 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
162 }
163 BR_IF => {
164 decrement_fuel!(T::get_flat_cost(BR_IF));
165 wasm.read_var_u32().unwrap_validated();
166
167 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
168
169 if test_val != 0 {
170 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
171 } else {
172 stp += 1;
173 }
174 trace!("Instruction: BR_IF");
175 }
176 BR_TABLE => {
177 decrement_fuel!(T::get_flat_cost(BR_TABLE));
178 let label_vec = wasm
179 .read_vec(|wasm| wasm.read_var_u32().map(|v| v as LabelIdx))
180 .unwrap_validated();
181 wasm.read_var_u32().unwrap_validated();
182
183 let case_val_i32: i32 = stack.pop_value().try_into().unwrap_validated();
185 let case_val = case_val_i32 as usize;
186
187 if case_val >= label_vec.len() {
188 stp += label_vec.len();
189 } else {
190 stp += case_val;
191 }
192
193 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
194 }
195 BR => {
196 decrement_fuel!(T::get_flat_cost(BR));
197 wasm.read_var_u32().unwrap_validated();
199 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
200 }
201 BLOCK => {
202 decrement_fuel!(T::get_flat_cost(BLOCK));
203 BlockType::read(wasm).unwrap_validated();
204 }
205 LOOP => {
206 decrement_fuel!(T::get_flat_cost(LOOP));
207 BlockType::read(wasm).unwrap_validated();
208 }
209 RETURN => {
210 decrement_fuel!(T::get_flat_cost(RETURN));
211 do_sidetable_control_transfer(wasm, stack, &mut stp, current_sidetable)?;
213 }
214 CALL => {
215 decrement_fuel!(T::get_flat_cost(CALL));
216 let local_func_idx = wasm.read_var_u32().unwrap_validated() as FuncIdx;
217 let FuncInst::WasmFunc(current_wasm_func_inst) =
218 store.functions.get(current_func_addr)
219 else {
220 unreachable!()
221 };
222
223 let func_to_call_addr = store
224 .modules
225 .get(current_wasm_func_inst.module_addr)
226 .func_addrs[local_func_idx];
227
228 let func_to_call_ty = store.functions.get(func_to_call_addr).ty();
229
230 trace!("Instruction: call [{func_to_call_addr:?}]");
231
232 match store.functions.get(func_to_call_addr) {
233 FuncInst::HostFunc(host_func_to_call_inst) => {
234 let params = stack
235 .pop_tail_iter(func_to_call_ty.params.valtypes.len())
236 .collect();
237 let returns =
238 (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
239
240 let returns = returns.map_err(|HaltExecutionError| {
241 RuntimeError::HostFunctionHaltedExecution
242 })?;
243
244 if returns.len() != func_to_call_ty.returns.valtypes.len() {
247 return Err(RuntimeError::HostFunctionSignatureMismatch);
248 }
249 for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
250 if value.to_ty() != ty {
251 return Err(RuntimeError::HostFunctionSignatureMismatch);
252 }
253 stack.push_value::<T>(value)?;
254 }
255 }
256 FuncInst::WasmFunc(wasm_func_to_call_inst) => {
257 let remaining_locals = &wasm_func_to_call_inst.locals;
258
259 stack.push_call_frame::<T>(
260 current_func_addr,
261 &func_to_call_ty,
262 remaining_locals,
263 wasm.pc,
264 stp,
265 )?;
266
267 current_func_addr = func_to_call_addr;
268 current_module = wasm_func_to_call_inst.module_addr;
269 wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
270 wasm.move_start_to(wasm_func_to_call_inst.code_expr)
271 .expect("code expression spans to always be valid");
272
273 stp = wasm_func_to_call_inst.stp;
274 current_sidetable = &store.modules.get(current_module).sidetable;
275 current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
276 + wasm_func_to_call_inst.code_expr.len();
277 }
278 }
279 trace!("Instruction: CALL");
280 }
281
282 CALL_INDIRECT => {
284 decrement_fuel!(T::get_flat_cost(CALL_INDIRECT));
285 let given_type_idx = wasm.read_var_u32().unwrap_validated() as TypeIdx;
286 let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
287
288 let table_addr = *store
289 .modules
290 .get(current_module)
291 .table_addrs
292 .get(table_idx)
293 .unwrap_validated();
294 let tab = store.tables.get(table_addr);
295 let func_ty = store
296 .modules
297 .get(current_module)
298 .types
299 .get(given_type_idx)
300 .unwrap_validated();
301
302 let i: u32 = stack.pop_value().try_into().unwrap_validated();
303
304 let r = tab
305 .elem
306 .get(i as usize)
307 .ok_or(TrapError::TableAccessOutOfBounds)
308 .and_then(|r| {
309 if matches!(r, Ref::Null(_)) {
310 trace!("table_idx ({table_idx}) --- element index in table ({i})");
311 Err(TrapError::UninitializedElement)
312 } else {
313 Ok(r)
314 }
315 })?;
316
317 let func_to_call_addr = match *r {
318 Ref::Func(func_addr) => func_addr,
319 Ref::Null(_) => return Err(TrapError::IndirectCallNullFuncRef.into()),
320 Ref::Extern(_) => unreachable_validated!(),
321 };
322
323 let func_to_call_ty = store.functions.get(func_to_call_addr).ty();
324 if *func_ty != func_to_call_ty {
325 return Err(TrapError::SignatureMismatch.into());
326 }
327
328 trace!("Instruction: call [{func_to_call_addr:?}]");
329
330 match store.functions.get(func_to_call_addr) {
331 FuncInst::HostFunc(host_func_to_call_inst) => {
332 let params = stack
333 .pop_tail_iter(func_to_call_ty.params.valtypes.len())
334 .collect();
335 let returns =
336 (host_func_to_call_inst.hostcode)(&mut store.user_data, params);
337
338 let returns = returns.map_err(|HaltExecutionError| {
339 RuntimeError::HostFunctionHaltedExecution
340 })?;
341
342 if returns.len() != func_to_call_ty.returns.valtypes.len() {
345 return Err(RuntimeError::HostFunctionSignatureMismatch);
346 }
347 for (value, ty) in zip(returns, func_to_call_ty.returns.valtypes) {
348 if value.to_ty() != ty {
349 return Err(RuntimeError::HostFunctionSignatureMismatch);
350 }
351 stack.push_value::<T>(value)?;
352 }
353 }
354 FuncInst::WasmFunc(wasm_func_to_call_inst) => {
355 let remaining_locals = &wasm_func_to_call_inst.locals;
356
357 stack.push_call_frame::<T>(
358 current_func_addr,
359 &func_to_call_ty,
360 remaining_locals,
361 wasm.pc,
362 stp,
363 )?;
364
365 current_func_addr = func_to_call_addr;
366 current_module = wasm_func_to_call_inst.module_addr;
367 wasm.full_wasm_binary = store.modules.get(current_module).wasm_bytecode;
368 wasm.move_start_to(wasm_func_to_call_inst.code_expr)
369 .expect("code expression spans to always be valid");
370
371 stp = wasm_func_to_call_inst.stp;
372 current_sidetable = &store.modules.get(current_module).sidetable;
373 current_function_end_marker = wasm_func_to_call_inst.code_expr.from()
374 + wasm_func_to_call_inst.code_expr.len();
375 }
376 }
377 trace!("Instruction: CALL_INDIRECT");
378 }
379 DROP => {
380 decrement_fuel!(T::get_flat_cost(DROP));
381 stack.pop_value();
382 trace!("Instruction: DROP");
383 }
384 SELECT => {
385 decrement_fuel!(T::get_flat_cost(SELECT));
386 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
387 let val2 = stack.pop_value();
388 let val1 = stack.pop_value();
389 if test_val != 0 {
390 stack.push_value::<T>(val1)?;
391 } else {
392 stack.push_value::<T>(val2)?;
393 }
394 trace!("Instruction: SELECT");
395 }
396 SELECT_T => {
397 decrement_fuel!(T::get_flat_cost(SELECT_T));
398 let _type_vec = wasm.read_vec(ValType::read).unwrap_validated();
399 let test_val: i32 = stack.pop_value().try_into().unwrap_validated();
400 let val2 = stack.pop_value();
401 let val1 = stack.pop_value();
402 if test_val != 0 {
403 stack.push_value::<T>(val1)?;
404 } else {
405 stack.push_value::<T>(val2)?;
406 }
407 trace!("Instruction: SELECT_T");
408 }
409 LOCAL_GET => {
410 decrement_fuel!(T::get_flat_cost(LOCAL_GET));
411 let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
412 let value = *stack.get_local(local_idx);
413 stack.push_value::<T>(value)?;
414 trace!("Instruction: local.get {} [] -> [t]", local_idx);
415 }
416 LOCAL_SET => {
417 decrement_fuel!(T::get_flat_cost(LOCAL_SET));
418 let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
419 let value = stack.pop_value();
420 *stack.get_local_mut(local_idx) = value;
421 trace!("Instruction: local.set {} [t] -> []", local_idx);
422 }
423 LOCAL_TEE => {
424 decrement_fuel!(T::get_flat_cost(LOCAL_TEE));
425 let local_idx = wasm.read_var_u32().unwrap_validated() as LocalIdx;
426 let value = stack.peek_value().unwrap_validated();
427 *stack.get_local_mut(local_idx) = value;
428 trace!("Instruction: local.tee {} [t] -> [t]", local_idx);
429 }
430 GLOBAL_GET => {
431 decrement_fuel!(T::get_flat_cost(GLOBAL_GET));
432 let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
433 let global_addr = *store
434 .modules
435 .get(current_module)
436 .global_addrs
437 .get(global_idx)
438 .unwrap_validated();
439 let global = store.globals.get(global_addr);
440
441 stack.push_value::<T>(global.value)?;
442
443 trace!(
444 "Instruction: global.get '{}' [<GLOBAL>] -> [{:?}]",
445 global_idx,
446 global.value
447 );
448 }
449 GLOBAL_SET => {
450 decrement_fuel!(T::get_flat_cost(GLOBAL_SET));
451 let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
452 let global_addr = *store
453 .modules
454 .get(current_module)
455 .global_addrs
456 .get(global_idx)
457 .unwrap_validated();
458 let global = store.globals.get_mut(global_addr);
459 global.value = stack.pop_value();
460 trace!("Instruction: GLOBAL_SET");
461 }
462 TABLE_GET => {
463 decrement_fuel!(T::get_flat_cost(TABLE_GET));
464 let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
465 let table_addr = *store
466 .modules
467 .get(current_module)
468 .table_addrs
469 .get(table_idx)
470 .unwrap_validated();
471 let tab = store.tables.get(table_addr);
472
473 let i: i32 = stack.pop_value().try_into().unwrap_validated();
474
475 let val = tab
476 .elem
477 .get(i as usize)
478 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
479
480 stack.push_value::<T>((*val).into())?;
481 trace!(
482 "Instruction: table.get '{}' [{}] -> [{}]",
483 table_idx,
484 i,
485 val
486 );
487 }
488 TABLE_SET => {
489 decrement_fuel!(T::get_flat_cost(TABLE_SET));
490 let table_idx = wasm.read_var_u32().unwrap_validated() as TableIdx;
491 let table_addr = *store
492 .modules
493 .get(current_module)
494 .table_addrs
495 .get(table_idx)
496 .unwrap_validated();
497 let tab = store.tables.get_mut(table_addr);
498
499 let val: Ref = stack.pop_value().try_into().unwrap_validated();
500 let i: i32 = stack.pop_value().try_into().unwrap_validated();
501
502 tab.elem
503 .get_mut(i as usize)
504 .ok_or(TrapError::TableOrElementAccessOutOfBounds)
505 .map(|r| *r = val)?;
506 trace!(
507 "Instruction: table.set '{}' [{} {}] -> []",
508 table_idx,
509 i,
510 val
511 )
512 }
513 UNREACHABLE => {
514 return Err(TrapError::ReachedUnreachable.into());
515 }
516 I32_LOAD => {
517 decrement_fuel!(T::get_flat_cost(I32_LOAD));
518 let memarg = MemArg::read(wasm).unwrap_validated();
519 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
520
521 let mem_addr = *store
522 .modules
523 .get(current_module)
524 .mem_addrs
525 .first()
526 .unwrap_validated();
527 let mem_inst = store.memories.get(mem_addr);
528
529 let idx = calculate_mem_address(&memarg, relative_address)?;
530 let data = mem_inst.mem.load(idx)?;
531
532 stack.push_value::<T>(Value::I32(data))?;
533 trace!("Instruction: i32.load [{relative_address}] -> [{data}]");
534 }
535 I64_LOAD => {
536 decrement_fuel!(T::get_flat_cost(I64_LOAD));
537 let memarg = MemArg::read(wasm).unwrap_validated();
538 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
539
540 let mem_addr = *store
541 .modules
542 .get(current_module)
543 .mem_addrs
544 .first()
545 .unwrap_validated();
546 let mem = store.memories.get(mem_addr);
547
548 let idx = calculate_mem_address(&memarg, relative_address)?;
549 let data = mem.mem.load(idx)?;
550
551 stack.push_value::<T>(Value::I64(data))?;
552 trace!("Instruction: i64.load [{relative_address}] -> [{data}]");
553 }
554 F32_LOAD => {
555 decrement_fuel!(T::get_flat_cost(F32_LOAD));
556 let memarg = MemArg::read(wasm).unwrap_validated();
557 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
558
559 let mem_addr = *store
560 .modules
561 .get(current_module)
562 .mem_addrs
563 .first()
564 .unwrap_validated();
565 let mem = store.memories.get(mem_addr);
566
567 let idx = calculate_mem_address(&memarg, relative_address)?;
568 let data = mem.mem.load(idx)?;
569
570 stack.push_value::<T>(Value::F32(data))?;
571 trace!("Instruction: f32.load [{relative_address}] -> [{data}]");
572 }
573 F64_LOAD => {
574 decrement_fuel!(T::get_flat_cost(F64_LOAD));
575 let memarg = MemArg::read(wasm).unwrap_validated();
576 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
577
578 let mem_addr = *store
579 .modules
580 .get(current_module)
581 .mem_addrs
582 .first()
583 .unwrap_validated();
584 let mem = store.memories.get(mem_addr);
585
586 let idx = calculate_mem_address(&memarg, relative_address)?;
587 let data = mem.mem.load(idx)?;
588
589 stack.push_value::<T>(Value::F64(data))?;
590 trace!("Instruction: f64.load [{relative_address}] -> [{data}]");
591 }
592 I32_LOAD8_S => {
593 decrement_fuel!(T::get_flat_cost(I32_LOAD8_S));
594 let memarg = MemArg::read(wasm).unwrap_validated();
595 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
596
597 let mem_addr = *store
598 .modules
599 .get(current_module)
600 .mem_addrs
601 .first()
602 .unwrap_validated();
603 let mem = store.memories.get(mem_addr);
604
605 let idx = calculate_mem_address(&memarg, relative_address)?;
606 let data: i8 = mem.mem.load(idx)?;
607
608 stack.push_value::<T>(Value::I32(data as u32))?;
609 trace!("Instruction: i32.load8_s [{relative_address}] -> [{data}]");
610 }
611 I32_LOAD8_U => {
612 decrement_fuel!(T::get_flat_cost(I32_LOAD8_U));
613 let memarg = MemArg::read(wasm).unwrap_validated();
614 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
615
616 let mem_addr = *store
617 .modules
618 .get(current_module)
619 .mem_addrs
620 .first()
621 .unwrap_validated();
622 let mem = store.memories.get(mem_addr);
623
624 let idx = calculate_mem_address(&memarg, relative_address)?;
625 let data: u8 = mem.mem.load(idx)?;
626
627 stack.push_value::<T>(Value::I32(data as u32))?;
628 trace!("Instruction: i32.load8_u [{relative_address}] -> [{data}]");
629 }
630 I32_LOAD16_S => {
631 decrement_fuel!(T::get_flat_cost(I32_LOAD16_S));
632 let memarg = MemArg::read(wasm).unwrap_validated();
633 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
634
635 let mem_addr = *store
636 .modules
637 .get(current_module)
638 .mem_addrs
639 .first()
640 .unwrap_validated();
641 let mem = store.memories.get(mem_addr);
642
643 let idx = calculate_mem_address(&memarg, relative_address)?;
644 let data: i16 = mem.mem.load(idx)?;
645
646 stack.push_value::<T>(Value::I32(data as u32))?;
647 trace!("Instruction: i32.load16_s [{relative_address}] -> [{data}]");
648 }
649 I32_LOAD16_U => {
650 decrement_fuel!(T::get_flat_cost(I32_LOAD16_U));
651 let memarg = MemArg::read(wasm).unwrap_validated();
652 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
653
654 let mem_addr = *store
655 .modules
656 .get(current_module)
657 .mem_addrs
658 .first()
659 .unwrap_validated();
660 let mem = store.memories.get(mem_addr);
661
662 let idx = calculate_mem_address(&memarg, relative_address)?;
663 let data: u16 = mem.mem.load(idx)?;
664
665 stack.push_value::<T>(Value::I32(data as u32))?;
666 trace!("Instruction: i32.load16_u [{relative_address}] -> [{data}]");
667 }
668 I64_LOAD8_S => {
669 decrement_fuel!(T::get_flat_cost(I64_LOAD8_S));
670 let memarg = MemArg::read(wasm).unwrap_validated();
671 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
672
673 let mem_addr = *store
674 .modules
675 .get(current_module)
676 .mem_addrs
677 .first()
678 .unwrap_validated();
679 let mem = store.memories.get(mem_addr);
680
681 let idx = calculate_mem_address(&memarg, relative_address)?;
682 let data: i8 = mem.mem.load(idx)?;
683
684 stack.push_value::<T>(Value::I64(data as u64))?;
685 trace!("Instruction: i64.load8_s [{relative_address}] -> [{data}]");
686 }
687 I64_LOAD8_U => {
688 decrement_fuel!(T::get_flat_cost(I64_LOAD8_U));
689 let memarg = MemArg::read(wasm).unwrap_validated();
690 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
691
692 let mem_addr = *store
693 .modules
694 .get(current_module)
695 .mem_addrs
696 .first()
697 .unwrap_validated();
698 let mem = store.memories.get(mem_addr);
699
700 let idx = calculate_mem_address(&memarg, relative_address)?;
701 let data: u8 = mem.mem.load(idx)?;
702
703 stack.push_value::<T>(Value::I64(data as u64))?;
704 trace!("Instruction: i64.load8_u [{relative_address}] -> [{data}]");
705 }
706 I64_LOAD16_S => {
707 decrement_fuel!(T::get_flat_cost(I64_LOAD16_S));
708 let memarg = MemArg::read(wasm).unwrap_validated();
709 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
710
711 let mem_addr = *store
712 .modules
713 .get(current_module)
714 .mem_addrs
715 .first()
716 .unwrap_validated();
717 let mem = store.memories.get(mem_addr);
718
719 let idx = calculate_mem_address(&memarg, relative_address)?;
720 let data: i16 = mem.mem.load(idx)?;
721
722 stack.push_value::<T>(Value::I64(data as u64))?;
723 trace!("Instruction: i64.load16_s [{relative_address}] -> [{data}]");
724 }
725 I64_LOAD16_U => {
726 decrement_fuel!(T::get_flat_cost(I64_LOAD16_U));
727 let memarg = MemArg::read(wasm).unwrap_validated();
728 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
729
730 let mem_addr = *store
731 .modules
732 .get(current_module)
733 .mem_addrs
734 .first()
735 .unwrap_validated();
736 let mem = store.memories.get(mem_addr);
737
738 let idx = calculate_mem_address(&memarg, relative_address)?;
739 let data: u16 = mem.mem.load(idx)?;
740
741 stack.push_value::<T>(Value::I64(data as u64))?;
742 trace!("Instruction: i64.load16_u [{relative_address}] -> [{data}]");
743 }
744 I64_LOAD32_S => {
745 decrement_fuel!(T::get_flat_cost(I64_LOAD32_S));
746 let memarg = MemArg::read(wasm).unwrap_validated();
747 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
748
749 let mem_addr = *store
750 .modules
751 .get(current_module)
752 .mem_addrs
753 .first()
754 .unwrap_validated();
755 let mem = store.memories.get(mem_addr);
756
757 let idx = calculate_mem_address(&memarg, relative_address)?;
758 let data: i32 = mem.mem.load(idx)?;
759
760 stack.push_value::<T>(Value::I64(data as u64))?;
761 trace!("Instruction: i64.load32_s [{relative_address}] -> [{data}]");
762 }
763 I64_LOAD32_U => {
764 decrement_fuel!(T::get_flat_cost(I64_LOAD32_U));
765 let memarg = MemArg::read(wasm).unwrap_validated();
766 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
767
768 let mem_addr = *store
769 .modules
770 .get(current_module)
771 .mem_addrs
772 .first()
773 .unwrap_validated();
774 let mem = store.memories.get(mem_addr);
775
776 let idx = calculate_mem_address(&memarg, relative_address)?;
777 let data: u32 = mem.mem.load(idx)?;
778
779 stack.push_value::<T>(Value::I64(data as u64))?;
780 trace!("Instruction: i64.load32_u [{relative_address}] -> [{data}]");
781 }
782 I32_STORE => {
783 decrement_fuel!(T::get_flat_cost(I32_STORE));
784 let memarg = MemArg::read(wasm).unwrap_validated();
785
786 let data_to_store: u32 = stack.pop_value().try_into().unwrap_validated();
787 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
788
789 let mem_addr = *store
790 .modules
791 .get(current_module)
792 .mem_addrs
793 .first()
794 .unwrap_validated();
795 let mem = store.memories.get(mem_addr);
796
797 let idx = calculate_mem_address(&memarg, relative_address)?;
798 mem.mem.store(idx, data_to_store)?;
799
800 trace!("Instruction: i32.store [{relative_address} {data_to_store}] -> []");
801 }
802 I64_STORE => {
803 decrement_fuel!(T::get_flat_cost(I64_STORE));
804 let memarg = MemArg::read(wasm).unwrap_validated();
805
806 let data_to_store: u64 = stack.pop_value().try_into().unwrap_validated();
807 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
808
809 let mem_addr = *store
810 .modules
811 .get(current_module)
812 .mem_addrs
813 .first()
814 .unwrap_validated();
815 let mem = store.memories.get(mem_addr);
816
817 let idx = calculate_mem_address(&memarg, relative_address)?;
818 mem.mem.store(idx, data_to_store)?;
819
820 trace!("Instruction: i64.store [{relative_address} {data_to_store}] -> []");
821 }
822 F32_STORE => {
823 decrement_fuel!(T::get_flat_cost(F32_STORE));
824 let memarg = MemArg::read(wasm).unwrap_validated();
825
826 let data_to_store: F32 = stack.pop_value().try_into().unwrap_validated();
827 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
828
829 let mem_addr = *store
830 .modules
831 .get(current_module)
832 .mem_addrs
833 .first()
834 .unwrap_validated();
835 let mem = store.memories.get(mem_addr);
836
837 let idx = calculate_mem_address(&memarg, relative_address)?;
838 mem.mem.store(idx, data_to_store)?;
839
840 trace!("Instruction: f32.store [{relative_address} {data_to_store}] -> []");
841 }
842 F64_STORE => {
843 decrement_fuel!(T::get_flat_cost(F64_STORE));
844 let memarg = MemArg::read(wasm).unwrap_validated();
845
846 let data_to_store: F64 = stack.pop_value().try_into().unwrap_validated();
847 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
848
849 let mem_addr = *store
850 .modules
851 .get(current_module)
852 .mem_addrs
853 .first()
854 .unwrap_validated();
855 let mem = store.memories.get(mem_addr);
856
857 let idx = calculate_mem_address(&memarg, relative_address)?;
858 mem.mem.store(idx, data_to_store)?;
859
860 trace!("Instruction: f64.store [{relative_address} {data_to_store}] -> []");
861 }
862 I32_STORE8 => {
863 decrement_fuel!(T::get_flat_cost(I32_STORE8));
864 let memarg = MemArg::read(wasm).unwrap_validated();
865
866 let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
867 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
868
869 let wrapped_data = data_to_store as i8;
870
871 let mem_addr = *store
872 .modules
873 .get(current_module)
874 .mem_addrs
875 .first()
876 .unwrap_validated();
877 let mem = store.memories.get(mem_addr);
878
879 let idx = calculate_mem_address(&memarg, relative_address)?;
880 mem.mem.store(idx, wrapped_data)?;
881
882 trace!("Instruction: i32.store8 [{relative_address} {wrapped_data}] -> []");
883 }
884 I32_STORE16 => {
885 decrement_fuel!(T::get_flat_cost(I32_STORE16));
886 let memarg = MemArg::read(wasm).unwrap_validated();
887
888 let data_to_store: i32 = stack.pop_value().try_into().unwrap_validated();
889 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
890
891 let wrapped_data = data_to_store as i16;
892
893 let mem_addr = *store
894 .modules
895 .get(current_module)
896 .mem_addrs
897 .first()
898 .unwrap_validated();
899 let mem = store.memories.get(mem_addr);
900
901 let idx = calculate_mem_address(&memarg, relative_address)?;
902 mem.mem.store(idx, wrapped_data)?;
903
904 trace!("Instruction: i32.store16 [{relative_address} {data_to_store}] -> []");
905 }
906 I64_STORE8 => {
907 decrement_fuel!(T::get_flat_cost(I64_STORE8));
908 let memarg = MemArg::read(wasm).unwrap_validated();
909
910 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
911 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
912
913 let wrapped_data = data_to_store as i8;
914
915 let mem_addr = *store
916 .modules
917 .get(current_module)
918 .mem_addrs
919 .first()
920 .unwrap_validated();
921 let mem = store.memories.get(mem_addr);
922
923 let idx = calculate_mem_address(&memarg, relative_address)?;
924 mem.mem.store(idx, wrapped_data)?;
925
926 trace!("Instruction: i64.store8 [{relative_address} {data_to_store}] -> []");
927 }
928 I64_STORE16 => {
929 decrement_fuel!(T::get_flat_cost(I64_STORE16));
930 let memarg = MemArg::read(wasm).unwrap_validated();
931
932 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
933 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
934
935 let wrapped_data = data_to_store as i16;
936
937 let mem_addr = *store
938 .modules
939 .get(current_module)
940 .mem_addrs
941 .first()
942 .unwrap_validated();
943 let mem = store.memories.get(mem_addr);
944
945 let idx = calculate_mem_address(&memarg, relative_address)?;
946 mem.mem.store(idx, wrapped_data)?;
947
948 trace!("Instruction: i64.store16 [{relative_address} {data_to_store}] -> []");
949 }
950 I64_STORE32 => {
951 decrement_fuel!(T::get_flat_cost(I64_STORE32));
952 let memarg = MemArg::read(wasm).unwrap_validated();
953
954 let data_to_store: i64 = stack.pop_value().try_into().unwrap_validated();
955 let relative_address: u32 = stack.pop_value().try_into().unwrap_validated();
956
957 let wrapped_data = data_to_store as i32;
958
959 let mem_addr = *store
960 .modules
961 .get(current_module)
962 .mem_addrs
963 .first()
964 .unwrap_validated();
965 let mem = store.memories.get(mem_addr);
966
967 let idx = calculate_mem_address(&memarg, relative_address)?;
968 mem.mem.store(idx, wrapped_data)?;
969
970 trace!("Instruction: i64.store32 [{relative_address} {data_to_store}] -> []");
971 }
972 MEMORY_SIZE => {
973 decrement_fuel!(T::get_flat_cost(MEMORY_SIZE));
974 let mem_idx = wasm.read_u8().unwrap_validated() as usize;
975 let mem_addr = *store
976 .modules
977 .get(current_module)
978 .mem_addrs
979 .get(mem_idx)
980 .unwrap_validated();
981 let mem = store.memories.get(mem_addr);
982 let size = mem.size() as u32;
983 stack.push_value::<T>(Value::I32(size))?;
984 trace!("Instruction: memory.size [] -> [{}]", size);
985 }
986 MEMORY_GROW => {
987 let mem_idx = wasm.read_u8().unwrap_validated() as usize;
988 let mem_addr = *store
989 .modules
990 .get(current_module)
991 .mem_addrs
992 .get(mem_idx)
993 .unwrap_validated();
994 let mem = store.memories.get_mut(mem_addr);
995 let sz: u32 = mem.size() as u32;
996
997 let n: u32 = stack.pop_value().try_into().unwrap_validated();
998 let cost = T::get_flat_cost(MEMORY_GROW)
1000 + u64::from(n) * T::get_cost_per_element(MEMORY_GROW);
1001 if let Some(fuel) = &mut resumable.maybe_fuel {
1002 if *fuel >= cost {
1003 *fuel -= cost;
1004 } else {
1005 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
1007 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
1009 return Ok(NonZeroU64::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 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_INIT);
2493 if let Some(fuel) = &mut resumable.maybe_fuel {
2494 if *fuel >= cost {
2495 *fuel -= cost;
2496 } else {
2497 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2499 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2501 return Ok(NonZeroU64::new(cost - *fuel));
2502 }
2503 }
2504
2505 let s: u32 = stack.pop_value().try_into().unwrap_validated();
2506 let d: u32 = stack.pop_value().try_into().unwrap_validated();
2507
2508 memory_init(
2509 &store.modules,
2510 &mut store.memories,
2511 &store.data,
2512 current_module,
2513 data_idx,
2514 mem_idx,
2515 n,
2516 s,
2517 d,
2518 )?;
2519 }
2520 DATA_DROP => {
2521 decrement_fuel!(T::get_fc_extension_flat_cost(DATA_DROP));
2522 let data_idx = wasm.read_var_u32().unwrap_validated() as DataIdx;
2523 data_drop(&store.modules, &mut store.data, current_module, data_idx)?;
2524 }
2525 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 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_COPY);
2540 if let Some(fuel) = &mut resumable.maybe_fuel {
2541 if *fuel >= cost {
2542 *fuel -= cost;
2543 } else {
2544 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2546 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2548 return Ok(NonZeroU64::new(cost - *fuel));
2549 }
2550 }
2551
2552 let s: i32 = stack.pop_value().try_into().unwrap_validated();
2553 let d: i32 = stack.pop_value().try_into().unwrap_validated();
2554
2555 let src_addr = *store
2556 .modules
2557 .get(current_module)
2558 .mem_addrs
2559 .get(src_idx)
2560 .unwrap_validated();
2561 let dst_addr = *store
2562 .modules
2563 .get(current_module)
2564 .mem_addrs
2565 .get(dst_idx)
2566 .unwrap_validated();
2567
2568 let src_mem = store.memories.get(src_addr);
2569 let dest_mem = store.memories.get(dst_addr);
2570
2571 dest_mem
2572 .mem
2573 .copy(d as usize, &src_mem.mem, s as usize, n as usize)?;
2574 trace!("Instruction: memory.copy");
2575 }
2576 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 + u64::from(n) * T::get_fc_extension_cost_per_element(MEMORY_FILL);
2595 if let Some(fuel) = &mut resumable.maybe_fuel {
2596 if *fuel >= cost {
2597 *fuel -= cost;
2598 } else {
2599 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2601 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2603 return Ok(NonZeroU64::new(cost - *fuel));
2604 }
2605 }
2606
2607 let val: i32 = stack.pop_value().try_into().unwrap_validated();
2608
2609 if !(0..=255).contains(&val) {
2610 warn!("Value for memory.fill does not fit in a byte ({val})");
2611 }
2612
2613 let d: i32 = stack.pop_value().try_into().unwrap_validated();
2614
2615 mem.mem.fill(d as usize, val as u8, n as usize)?;
2616
2617 trace!("Instruction: memory.fill");
2618 }
2619 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 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_INIT);
2630 if let Some(fuel) = &mut resumable.maybe_fuel {
2631 if *fuel >= cost {
2632 *fuel -= cost;
2633 } else {
2634 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2636 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2638 return Ok(NonZeroU64::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 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_COPY);
2688 if let Some(fuel) = &mut resumable.maybe_fuel {
2689 if *fuel >= cost {
2690 *fuel -= cost;
2691 } else {
2692 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2694 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2696 return Ok(NonZeroU64::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 + u64::from(n) * T::get_fc_extension_cost_per_element(TABLE_GROW);
2785 if let Some(fuel) = &mut resumable.maybe_fuel {
2786 if *fuel >= cost {
2787 *fuel -= cost;
2788 } else {
2789 stack.push_value::<T>(Value::I32(n)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2791 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2793 return Ok(NonZeroU64::new(cost - *fuel));
2794 }
2795 }
2796
2797 let val: Ref = stack.pop_value().try_into().unwrap_validated();
2798
2799 match tab.grow(n, val) {
2803 Ok(_) => {
2804 stack.push_value::<T>(Value::I32(sz))?;
2805 }
2806 Err(_) => {
2807 stack.push_value::<T>(Value::I32(u32::MAX))?;
2808 }
2809 }
2810 }
2811 TABLE_SIZE => {
2812 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_SIZE));
2813 let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2814 let table_addr = *store
2815 .modules
2816 .get(current_module)
2817 .table_addrs
2818 .get(table_idx)
2819 .unwrap_validated();
2820 let tab = store.tables.get(table_addr);
2821
2822 let sz = tab.elem.len() as u32;
2823
2824 stack.push_value::<T>(Value::I32(sz))?;
2825
2826 trace!("Instruction: table.size '{}' [] -> [{}]", table_idx, sz);
2827 }
2828 TABLE_FILL => {
2829 decrement_fuel!(T::get_fc_extension_flat_cost(TABLE_FILL));
2830 let table_idx = wasm.read_var_u32().unwrap_validated() as usize;
2831 let table_addr = *store
2832 .modules
2833 .get(current_module)
2834 .table_addrs
2835 .get(table_idx)
2836 .unwrap_validated();
2837 let tab = store.tables.get_mut(table_addr);
2838
2839 let len: u32 = stack.pop_value().try_into().unwrap_validated();
2840 let cost = T::get_fc_extension_flat_cost(TABLE_FILL)
2841 + u64::from(len) * T::get_fc_extension_cost_per_element(TABLE_FILL);
2842 if let Some(fuel) = &mut resumable.maybe_fuel {
2843 if *fuel >= cost {
2844 *fuel -= cost;
2845 } else {
2846 stack.push_value::<T>(Value::I32(len)).unwrap_validated(); resumable.current_func_addr = current_func_addr;
2848 resumable.pc = wasm.pc - prev_pc; resumable.stp = stp;
2850 return Ok(NonZeroU64::new(cost - *fuel));
2851 }
2852 }
2853
2854 let val: Ref = stack.pop_value().try_into().unwrap_validated();
2855 let dst: u32 = stack.pop_value().try_into().unwrap_validated();
2856
2857 let end = (dst as usize)
2858 .checked_add(len as usize)
2859 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
2860
2861 tab.elem
2862 .get_mut(dst as usize..end)
2863 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?
2864 .fill(val);
2865
2866 trace!(
2867 "Instruction table.fill '{}' [{} {} {}] -> []",
2868 table_idx,
2869 dst,
2870 val,
2871 len
2872 )
2873 }
2874 _ => unreachable!(),
2875 }
2876 }
2877
2878 I32_EXTEND8_S => {
2879 decrement_fuel!(T::get_flat_cost(I32_EXTEND8_S));
2880 let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
2881
2882 if v | 0xFF != 0xFF {
2883 trace!("Number v ({}) not contained in 8 bits, truncating", v);
2884 v &= 0xFF;
2885 }
2886
2887 let res = if v | 0x7F != 0x7F { v | 0xFFFFFF00 } else { v };
2888
2889 stack.push_value::<T>(res.into())?;
2890
2891 trace!("Instruction i32.extend8_s [{}] -> [{}]", v, res);
2892 }
2893 I32_EXTEND16_S => {
2894 decrement_fuel!(T::get_flat_cost(I32_EXTEND16_S));
2895 let mut v: u32 = stack.pop_value().try_into().unwrap_validated();
2896
2897 if v | 0xFFFF != 0xFFFF {
2898 trace!("Number v ({}) not contained in 16 bits, truncating", v);
2899 v &= 0xFFFF;
2900 }
2901
2902 let res = if v | 0x7FFF != 0x7FFF {
2903 v | 0xFFFF0000
2904 } else {
2905 v
2906 };
2907
2908 stack.push_value::<T>(res.into())?;
2909
2910 trace!("Instruction i32.extend16_s [{}] -> [{}]", v, res);
2911 }
2912 I64_EXTEND8_S => {
2913 decrement_fuel!(T::get_flat_cost(I64_EXTEND8_S));
2914 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2915
2916 if v | 0xFF != 0xFF {
2917 trace!("Number v ({}) not contained in 8 bits, truncating", v);
2918 v &= 0xFF;
2919 }
2920
2921 let res = if v | 0x7F != 0x7F {
2922 v | 0xFFFFFFFF_FFFFFF00
2923 } else {
2924 v
2925 };
2926
2927 stack.push_value::<T>(res.into())?;
2928
2929 trace!("Instruction i64.extend8_s [{}] -> [{}]", v, res);
2930 }
2931 I64_EXTEND16_S => {
2932 decrement_fuel!(T::get_flat_cost(I64_EXTEND16_S));
2933 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2934
2935 if v | 0xFFFF != 0xFFFF {
2936 trace!("Number v ({}) not contained in 16 bits, truncating", v);
2937 v &= 0xFFFF;
2938 }
2939
2940 let res = if v | 0x7FFF != 0x7FFF {
2941 v | 0xFFFFFFFF_FFFF0000
2942 } else {
2943 v
2944 };
2945
2946 stack.push_value::<T>(res.into())?;
2947
2948 trace!("Instruction i64.extend16_s [{}] -> [{}]", v, res);
2949 }
2950 I64_EXTEND32_S => {
2951 decrement_fuel!(T::get_flat_cost(I64_EXTEND32_S));
2952 let mut v: u64 = stack.pop_value().try_into().unwrap_validated();
2953
2954 if v | 0xFFFF_FFFF != 0xFFFF_FFFF {
2955 trace!("Number v ({}) not contained in 32 bits, truncating", v);
2956 v &= 0xFFFF_FFFF;
2957 }
2958
2959 let res = if v | 0x7FFF_FFFF != 0x7FFF_FFFF {
2960 v | 0xFFFFFFFF_00000000
2961 } else {
2962 v
2963 };
2964
2965 stack.push_value::<T>(res.into())?;
2966
2967 trace!("Instruction i64.extend32_s [{}] -> [{}]", v, res);
2968 }
2969 FD_EXTENSIONS => {
2970 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() || lane.is_negative_infinity() {
5095 u32::MIN
5096 } else if lane.is_infinity() {
5097 u32::MAX
5098 } else {
5099 lane.as_u32()
5100 }
5101 });
5102 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5103 }
5104 I32X4_TRUNC_SAT_F64X2_S_ZERO => {
5105 decrement_fuel!(T::get_fd_extension_flat_cost(
5106 I32X4_TRUNC_SAT_F64X2_S_ZERO
5107 ));
5108 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5109 let lanes: [F64; 2] = to_lanes(data);
5110 let result = lanes.map(|lane| {
5111 if lane.is_nan() {
5112 0
5113 } else if lane.is_negative_infinity() {
5114 i32::MIN
5115 } else if lane.is_infinity() {
5116 i32::MAX
5117 } else {
5118 lane.as_i32()
5119 }
5120 });
5121 stack.push_value::<T>(Value::V128(from_lanes([
5122 result[0], result[1], 0, 0,
5123 ])))?;
5124 }
5125 I32X4_TRUNC_SAT_F64X2_U_ZERO => {
5126 decrement_fuel!(T::get_fd_extension_flat_cost(
5127 I32X4_TRUNC_SAT_F64X2_U_ZERO
5128 ));
5129 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5130 let lanes: [F64; 2] = to_lanes(data);
5131 let result = lanes.map(|lane| {
5132 if lane.is_nan() || lane.is_negative_infinity() {
5133 u32::MIN
5134 } else if lane.is_infinity() {
5135 u32::MAX
5136 } else {
5137 lane.as_u32()
5138 }
5139 });
5140 stack.push_value::<T>(Value::V128(from_lanes([
5141 result[0], result[1], 0, 0,
5142 ])))?;
5143 }
5144 F32X4_CONVERT_I32X4_S => {
5145 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_S));
5146 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5147 let lanes: [i32; 4] = to_lanes(data);
5148 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5149 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5150 }
5151 F32X4_CONVERT_I32X4_U => {
5152 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_CONVERT_I32X4_U));
5153 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5154 let lanes: [u32; 4] = to_lanes(data);
5155 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
5156 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5157 }
5158 F64X2_CONVERT_LOW_I32X4_S => {
5159 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_S));
5160 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5161 let lanes: [i32; 4] = to_lanes(data);
5162 let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
5163 let result = low_lanes.map(|lane| F64(lane as f64));
5164 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5165 }
5166 F64X2_CONVERT_LOW_I32X4_U => {
5167 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_CONVERT_LOW_I32X4_U));
5168 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5169 let lanes: [u32; 4] = to_lanes(data);
5170 let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
5171 let result = low_lanes.map(|lane| F64(lane as f64));
5172 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5173 }
5174 F32X4_DEMOTE_F64X2_ZERO => {
5175 decrement_fuel!(T::get_fd_extension_flat_cost(F32X4_DEMOTE_F64X2_ZERO));
5176 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5177 let lanes = to_lanes::<8, 2, F64>(data);
5178 let half_lanes = lanes.map(|lane| lane.as_f32());
5179 let result = [half_lanes[0], half_lanes[1], F32(0.0), F32(0.0)];
5180 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5181 }
5182 F64X2_PROMOTE_LOW_F32X4 => {
5183 decrement_fuel!(T::get_fd_extension_flat_cost(F64X2_PROMOTE_LOW_F32X4));
5184 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5185 let lanes: [F32; 4] = to_lanes(data);
5186 let half_lanes: [F32; 2] = lanes[..2].try_into().unwrap();
5187 let result = half_lanes.map(|lane| lane.as_f64());
5188 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5189 }
5190
5191 I8X16_NARROW_I16X8_S => {
5193 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_S));
5194 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5195 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5196 let lanes2: [i16; 8] = to_lanes(data2);
5197 let lanes1: [i16; 8] = to_lanes(data1);
5198 let mut concatenated_narrowed_lanes = lanes1
5199 .into_iter()
5200 .chain(lanes2)
5201 .map(|lane| lane.clamp(i8::MIN as i16, i8::MAX as i16) as i8);
5202 let result: [i8; 16] =
5203 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5204 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5205 }
5206 I8X16_NARROW_I16X8_U => {
5207 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_NARROW_I16X8_U));
5208 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5209 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5210 let lanes2: [i16; 8] = to_lanes(data2);
5211 let lanes1: [i16; 8] = to_lanes(data1);
5212 let mut concatenated_narrowed_lanes = lanes1
5213 .into_iter()
5214 .chain(lanes2)
5215 .map(|lane| lane.clamp(u8::MIN as i16, u8::MAX as i16) as u8);
5216 let result: [u8; 16] =
5217 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5218 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5219 }
5220 I16X8_NARROW_I32X4_S => {
5221 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_S));
5222 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5223 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5224 let lanes2: [i32; 4] = to_lanes(data2);
5225 let lanes1: [i32; 4] = to_lanes(data1);
5226 let mut concatenated_narrowed_lanes = lanes1
5227 .into_iter()
5228 .chain(lanes2)
5229 .map(|lane| lane.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
5230 let result: [i16; 8] =
5231 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5232 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5233 }
5234 I16X8_NARROW_I32X4_U => {
5235 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_NARROW_I32X4_U));
5236 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5237 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5238 let lanes2: [i32; 4] = to_lanes(data2);
5239 let lanes1: [i32; 4] = to_lanes(data1);
5240 let mut concatenated_narrowed_lanes = lanes1
5241 .into_iter()
5242 .chain(lanes2)
5243 .map(|lane| lane.clamp(u16::MIN as i32, u16::MAX as i32) as u16);
5244 let result: [u16; 8] =
5245 array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
5246 stack.push_value::<T>(Value::V128(from_lanes(result)))?;
5247 }
5248
5249 I8X16_BITMASK => {
5251 decrement_fuel!(T::get_fd_extension_flat_cost(I8X16_BITMASK));
5252 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5253 let lanes: [i8; 16] = to_lanes(data);
5254 let bits = lanes.map(|lane| lane < 0);
5255 let bitmask = bits
5256 .into_iter()
5257 .enumerate()
5258 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5259 stack.push_value::<T>(Value::I32(bitmask))?;
5260 }
5261 I16X8_BITMASK => {
5262 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_BITMASK));
5263 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5264 let lanes: [i16; 8] = to_lanes(data);
5265 let bits = lanes.map(|lane| lane < 0);
5266 let bitmask = bits
5267 .into_iter()
5268 .enumerate()
5269 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5270 stack.push_value::<T>(Value::I32(bitmask))?;
5271 }
5272 I32X4_BITMASK => {
5273 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_BITMASK));
5274 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5275 let lanes: [i32; 4] = to_lanes(data);
5276 let bits = lanes.map(|lane| lane < 0);
5277 let bitmask = bits
5278 .into_iter()
5279 .enumerate()
5280 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5281 stack.push_value::<T>(Value::I32(bitmask))?;
5282 }
5283 I64X2_BITMASK => {
5284 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_BITMASK));
5285 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5286 let lanes: [i64; 2] = to_lanes(data);
5287 let bits = lanes.map(|lane| lane < 0);
5288 let bitmask = bits
5289 .into_iter()
5290 .enumerate()
5291 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
5292 stack.push_value::<T>(Value::I32(bitmask))?;
5293 }
5294
5295 I32X4_DOT_I16X8_S => {
5297 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_DOT_I16X8_S));
5298 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5299 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5300 let lanes1: [i16; 8] = to_lanes(data1);
5301 let lanes2: [i16; 8] = to_lanes(data2);
5302 let multiplied: [i32; 8] = array::from_fn(|i| {
5303 let v1 = lanes1[i] as i32;
5304 let v2 = lanes2[i] as i32;
5305 v1.wrapping_mul(v2)
5306 });
5307 let added: [i32; 4] = array::from_fn(|i| {
5308 let v1 = multiplied[2 * i];
5309 let v2 = multiplied[2 * i + 1];
5310 v1.wrapping_add(v2)
5311 });
5312 stack.push_value::<T>(Value::V128(from_lanes(added)))?;
5313 }
5314
5315 I16X8_EXTMUL_HIGH_I8X16_S => {
5317 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_S));
5318 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5319 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5320 let lanes1: [i8; 16] = to_lanes(data1);
5321 let lanes2: [i8; 16] = to_lanes(data2);
5322 let high_lanes1: [i8; 8] = lanes1[8..].try_into().unwrap();
5323 let high_lanes2: [i8; 8] = lanes2[8..].try_into().unwrap();
5324 let multiplied: [i16; 8] = array::from_fn(|i| {
5325 let v1 = high_lanes1[i] as i16;
5326 let v2 = high_lanes2[i] as i16;
5327 v1.wrapping_mul(v2)
5328 });
5329 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5330 }
5331 I16X8_EXTMUL_HIGH_I8X16_U => {
5332 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_HIGH_I8X16_U));
5333 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5334 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5335 let lanes1: [u8; 16] = to_lanes(data1);
5336 let lanes2: [u8; 16] = to_lanes(data2);
5337 let high_lanes1: [u8; 8] = lanes1[8..].try_into().unwrap();
5338 let high_lanes2: [u8; 8] = lanes2[8..].try_into().unwrap();
5339 let multiplied: [u16; 8] = array::from_fn(|i| {
5340 let v1 = high_lanes1[i] as u16;
5341 let v2 = high_lanes2[i] as u16;
5342 v1.wrapping_mul(v2)
5343 });
5344 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5345 }
5346 I16X8_EXTMUL_LOW_I8X16_S => {
5347 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_S));
5348 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5349 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5350 let lanes1: [i8; 16] = to_lanes(data1);
5351 let lanes2: [i8; 16] = to_lanes(data2);
5352 let high_lanes1: [i8; 8] = lanes1[..8].try_into().unwrap();
5353 let high_lanes2: [i8; 8] = lanes2[..8].try_into().unwrap();
5354 let multiplied: [i16; 8] = array::from_fn(|i| {
5355 let v1 = high_lanes1[i] as i16;
5356 let v2 = high_lanes2[i] as i16;
5357 v1.wrapping_mul(v2)
5358 });
5359 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5360 }
5361 I16X8_EXTMUL_LOW_I8X16_U => {
5362 decrement_fuel!(T::get_fd_extension_flat_cost(I16X8_EXTMUL_LOW_I8X16_U));
5363 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5364 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5365 let lanes1: [u8; 16] = to_lanes(data1);
5366 let lanes2: [u8; 16] = to_lanes(data2);
5367 let high_lanes1: [u8; 8] = lanes1[..8].try_into().unwrap();
5368 let high_lanes2: [u8; 8] = lanes2[..8].try_into().unwrap();
5369 let multiplied: [u16; 8] = array::from_fn(|i| {
5370 let v1 = high_lanes1[i] as u16;
5371 let v2 = high_lanes2[i] as u16;
5372 v1.wrapping_mul(v2)
5373 });
5374 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5375 }
5376 I32X4_EXTMUL_HIGH_I16X8_S => {
5377 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_S));
5378 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5379 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5380 let lanes1: [i16; 8] = to_lanes(data1);
5381 let lanes2: [i16; 8] = to_lanes(data2);
5382 let high_lanes1: [i16; 4] = lanes1[4..].try_into().unwrap();
5383 let high_lanes2: [i16; 4] = lanes2[4..].try_into().unwrap();
5384 let multiplied: [i32; 4] = array::from_fn(|i| {
5385 let v1 = high_lanes1[i] as i32;
5386 let v2 = high_lanes2[i] as i32;
5387 v1.wrapping_mul(v2)
5388 });
5389 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5390 }
5391 I32X4_EXTMUL_HIGH_I16X8_U => {
5392 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_HIGH_I16X8_U));
5393 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5394 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5395 let lanes1: [u16; 8] = to_lanes(data1);
5396 let lanes2: [u16; 8] = to_lanes(data2);
5397 let high_lanes1: [u16; 4] = lanes1[4..].try_into().unwrap();
5398 let high_lanes2: [u16; 4] = lanes2[4..].try_into().unwrap();
5399 let multiplied: [u32; 4] = array::from_fn(|i| {
5400 let v1 = high_lanes1[i] as u32;
5401 let v2 = high_lanes2[i] as u32;
5402 v1.wrapping_mul(v2)
5403 });
5404 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5405 }
5406 I32X4_EXTMUL_LOW_I16X8_S => {
5407 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_S));
5408 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5409 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5410 let lanes1: [i16; 8] = to_lanes(data1);
5411 let lanes2: [i16; 8] = to_lanes(data2);
5412 let high_lanes1: [i16; 4] = lanes1[..4].try_into().unwrap();
5413 let high_lanes2: [i16; 4] = lanes2[..4].try_into().unwrap();
5414 let multiplied: [i32; 4] = array::from_fn(|i| {
5415 let v1 = high_lanes1[i] as i32;
5416 let v2 = high_lanes2[i] as i32;
5417 v1.wrapping_mul(v2)
5418 });
5419 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5420 }
5421 I32X4_EXTMUL_LOW_I16X8_U => {
5422 decrement_fuel!(T::get_fd_extension_flat_cost(I32X4_EXTMUL_LOW_I16X8_U));
5423 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5424 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5425 let lanes1: [u16; 8] = to_lanes(data1);
5426 let lanes2: [u16; 8] = to_lanes(data2);
5427 let high_lanes1: [u16; 4] = lanes1[..4].try_into().unwrap();
5428 let high_lanes2: [u16; 4] = lanes2[..4].try_into().unwrap();
5429 let multiplied: [u32; 4] = array::from_fn(|i| {
5430 let v1 = high_lanes1[i] as u32;
5431 let v2 = high_lanes2[i] as u32;
5432 v1.wrapping_mul(v2)
5433 });
5434 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5435 }
5436 I64X2_EXTMUL_HIGH_I32X4_S => {
5437 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_S));
5438 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5439 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5440 let lanes1: [i32; 4] = to_lanes(data1);
5441 let lanes2: [i32; 4] = to_lanes(data2);
5442 let high_lanes1: [i32; 2] = lanes1[2..].try_into().unwrap();
5443 let high_lanes2: [i32; 2] = lanes2[2..].try_into().unwrap();
5444 let multiplied: [i64; 2] = array::from_fn(|i| {
5445 let v1 = high_lanes1[i] as i64;
5446 let v2 = high_lanes2[i] as i64;
5447 v1.wrapping_mul(v2)
5448 });
5449 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5450 }
5451 I64X2_EXTMUL_HIGH_I32X4_U => {
5452 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_HIGH_I32X4_U));
5453 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5454 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5455 let lanes1: [u32; 4] = to_lanes(data1);
5456 let lanes2: [u32; 4] = to_lanes(data2);
5457 let high_lanes1: [u32; 2] = lanes1[2..].try_into().unwrap();
5458 let high_lanes2: [u32; 2] = lanes2[2..].try_into().unwrap();
5459 let multiplied: [u64; 2] = array::from_fn(|i| {
5460 let v1 = high_lanes1[i] as u64;
5461 let v2 = high_lanes2[i] as u64;
5462 v1.wrapping_mul(v2)
5463 });
5464 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5465 }
5466 I64X2_EXTMUL_LOW_I32X4_S => {
5467 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_S));
5468 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5469 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5470 let lanes1: [i32; 4] = to_lanes(data1);
5471 let lanes2: [i32; 4] = to_lanes(data2);
5472 let high_lanes1: [i32; 2] = lanes1[..2].try_into().unwrap();
5473 let high_lanes2: [i32; 2] = lanes2[..2].try_into().unwrap();
5474 let multiplied: [i64; 2] = array::from_fn(|i| {
5475 let v1 = high_lanes1[i] as i64;
5476 let v2 = high_lanes2[i] as i64;
5477 v1.wrapping_mul(v2)
5478 });
5479 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5480 }
5481 I64X2_EXTMUL_LOW_I32X4_U => {
5482 decrement_fuel!(T::get_fd_extension_flat_cost(I64X2_EXTMUL_LOW_I32X4_U));
5483 let data1: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5484 let data2: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5485 let lanes1: [u32; 4] = to_lanes(data1);
5486 let lanes2: [u32; 4] = to_lanes(data2);
5487 let high_lanes1: [u32; 2] = lanes1[..2].try_into().unwrap();
5488 let high_lanes2: [u32; 2] = lanes2[..2].try_into().unwrap();
5489 let multiplied: [u64; 2] = array::from_fn(|i| {
5490 let v1 = high_lanes1[i] as u64;
5491 let v2 = high_lanes2[i] as u64;
5492 v1.wrapping_mul(v2)
5493 });
5494 stack.push_value::<T>(Value::V128(from_lanes(multiplied)))?;
5495 }
5496
5497 I16X8_EXTADD_PAIRWISE_I8X16_S => {
5499 decrement_fuel!(T::get_fd_extension_flat_cost(
5500 I16X8_EXTADD_PAIRWISE_I8X16_S
5501 ));
5502 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5503 let lanes: [i8; 16] = to_lanes(data);
5504 let added_pairwise: [i16; 8] = array::from_fn(|i| {
5505 let v1 = lanes[2 * i] as i16;
5506 let v2 = lanes[2 * i + 1] as i16;
5507 v1.wrapping_add(v2)
5508 });
5509 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5510 }
5511 I16X8_EXTADD_PAIRWISE_I8X16_U => {
5512 decrement_fuel!(T::get_fd_extension_flat_cost(
5513 I16X8_EXTADD_PAIRWISE_I8X16_U
5514 ));
5515 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5516 let lanes: [u8; 16] = to_lanes(data);
5517 let added_pairwise: [u16; 8] = array::from_fn(|i| {
5518 let v1 = lanes[2 * i] as u16;
5519 let v2 = lanes[2 * i + 1] as u16;
5520 v1.wrapping_add(v2)
5521 });
5522 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5523 }
5524 I32X4_EXTADD_PAIRWISE_I16X8_S => {
5525 decrement_fuel!(T::get_fd_extension_flat_cost(
5526 I32X4_EXTADD_PAIRWISE_I16X8_S
5527 ));
5528 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5529 let lanes: [i16; 8] = to_lanes(data);
5530 let added_pairwise: [i32; 4] = array::from_fn(|i| {
5531 let v1 = lanes[2 * i] as i32;
5532 let v2 = lanes[2 * i + 1] as i32;
5533 v1.wrapping_add(v2)
5534 });
5535 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5536 }
5537 I32X4_EXTADD_PAIRWISE_I16X8_U => {
5538 decrement_fuel!(T::get_fd_extension_flat_cost(
5539 I32X4_EXTADD_PAIRWISE_I16X8_U
5540 ));
5541 let data: [u8; 16] = stack.pop_value().try_into().unwrap_validated();
5542 let lanes: [u16; 8] = to_lanes(data);
5543 let added_pairwise: [u32; 4] = array::from_fn(|i| {
5544 let v1 = lanes[2 * i] as u32;
5545 let v2 = lanes[2 * i + 1] as u32;
5546 v1.wrapping_add(v2)
5547 });
5548 stack.push_value::<T>(Value::V128(from_lanes(added_pairwise)))?;
5549 }
5550
5551 F32X4_RELAXED_MADD
5553 | F32X4_RELAXED_MAX
5554 | F32X4_RELAXED_MIN
5555 | F32X4_RELAXED_NMADD
5556 | F64X2_RELAXED_MADD
5557 | F64X2_RELAXED_MAX
5558 | F64X2_RELAXED_MIN
5559 | F64X2_RELAXED_NMADD
5560 | I16X8_RELAXED_LANESELECT
5561 | I32X4_RELAXED_LANESELECT
5562 | I32X4_RELAXED_TRUNC_F32X4_S
5563 | I32X4_RELAXED_TRUNC_F32X4_U
5564 | I32X4_RELAXED_TRUNC_F64X2_S_ZERO
5565 | I32X4_RELAXED_TRUNC_F64X2_U_ZERO
5566 | I64X2_RELAXED_LANESELECT
5567 | I8X16_RELAXED_LANESELECT
5568 | I8X16_RELAXED_SWIZZLE
5569 | 154
5570 | 187
5571 | 194
5572 | 256.. => unreachable_validated!(),
5573 }
5574 }
5575
5576 0x06..=0x0A
5578 | 0x12..=0x19
5579 | 0x1C..=0x1F
5580 | 0x25..=0x27
5581 | 0xC0..=0xFA
5582 | 0xFB
5583 | 0xFE
5584 | 0xFF => {
5585 unreachable_validated!();
5586 }
5587 }
5588 }
5589 Ok(None)
5590}
5591
5592fn do_sidetable_control_transfer(
5594 wasm: &mut WasmReader,
5595 stack: &mut Stack,
5596 current_stp: &mut usize,
5597 current_sidetable: &Sidetable,
5598) -> Result<(), RuntimeError> {
5599 let sidetable_entry = ¤t_sidetable[*current_stp];
5600
5601 stack.remove_in_between(sidetable_entry.popcnt, sidetable_entry.valcnt);
5602
5603 *current_stp = (*current_stp as isize + sidetable_entry.delta_stp) as usize;
5604 wasm.pc = (wasm.pc as isize + sidetable_entry.delta_pc) as usize;
5605
5606 Ok(())
5607}
5608
5609#[inline(always)]
5610fn calculate_mem_address(memarg: &MemArg, relative_address: u32) -> Result<usize, RuntimeError> {
5611 memarg
5612 .offset
5613 .checked_add(relative_address)
5618 .ok_or(TrapError::MemoryOrDataAccessOutOfBounds)?
5619 .try_into()
5620 .map_err(|_| TrapError::MemoryOrDataAccessOutOfBounds.into())
5621}
5622
5623#[inline(always)]
5625#[allow(clippy::too_many_arguments)]
5626pub(super) fn table_init(
5627 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5628 store_tables: &mut AddrVec<TableAddr, TableInst>,
5629 store_elements: &AddrVec<ElemAddr, ElemInst>,
5630 current_module: ModuleAddr,
5631 elem_idx: usize,
5632 table_idx: usize,
5633 n: u32,
5634 s: i32,
5635 d: i32,
5636) -> Result<(), RuntimeError> {
5637 let tab_addr = *store_modules
5638 .get(current_module)
5639 .table_addrs
5640 .get(table_idx)
5641 .unwrap_validated();
5642 let elem_addr = *store_modules
5643 .get(current_module)
5644 .elem_addrs
5645 .get(elem_idx)
5646 .unwrap_validated();
5647
5648 let tab = store_tables.get_mut(tab_addr);
5649
5650 let elem = store_elements.get(elem_addr);
5651
5652 trace!(
5653 "Instruction: table.init '{}' '{}' [{} {} {}] -> []",
5654 elem_idx,
5655 table_idx,
5656 d,
5657 s,
5658 n
5659 );
5660
5661 let final_src_offset = (s as usize)
5662 .checked_add(n as usize)
5663 .filter(|&res| res <= elem.len())
5664 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
5665
5666 if (d as usize)
5667 .checked_add(n as usize)
5668 .filter(|&res| res <= tab.len())
5669 .is_none()
5670 {
5671 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
5672 }
5673
5674 let dest = &mut tab.elem[d as usize..];
5675 let src = &elem.references[s as usize..final_src_offset];
5676 dest[..src.len()].copy_from_slice(src);
5677 Ok(())
5678}
5679
5680#[inline(always)]
5681pub(super) fn elem_drop(
5682 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5683 store_elements: &mut AddrVec<ElemAddr, ElemInst>,
5684 current_module: ModuleAddr,
5685 elem_idx: usize,
5686) -> Result<(), RuntimeError> {
5687 let elem_addr = *store_modules
5689 .get(current_module)
5690 .elem_addrs
5691 .get(elem_idx)
5692 .unwrap_validated();
5693 store_elements.get_mut(elem_addr).references.clear();
5694 Ok(())
5695}
5696
5697#[inline(always)]
5698#[allow(clippy::too_many_arguments)]
5699pub(super) fn memory_init(
5700 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5701 store_memories: &mut AddrVec<MemAddr, MemInst>,
5702 store_data: &AddrVec<DataAddr, DataInst>,
5703 current_module: ModuleAddr,
5704 data_idx: usize,
5705 mem_idx: usize,
5706 n: u32,
5707 s: u32,
5708 d: u32,
5709) -> Result<(), RuntimeError> {
5710 let n = usize::try_from(n).expect("pointer width to be at least 32 bits wide");
5711 let s = usize::try_from(s).expect("pointer width to be at least 32 bits wide");
5712 let d = usize::try_from(d).expect("pointer width to be at least 32 bits wide");
5713
5714 let mem_addr = *store_modules
5715 .get(current_module)
5716 .mem_addrs
5717 .get(mem_idx)
5718 .unwrap_validated();
5719 let mem = store_memories.get(mem_addr);
5720
5721 mem.mem.init(
5722 d,
5723 &store_data
5724 .get(store_modules.get(current_module).data_addrs[data_idx])
5725 .data,
5726 s,
5727 n,
5728 )?;
5729
5730 trace!("Instruction: memory.init");
5731 Ok(())
5732}
5733
5734#[inline(always)]
5735pub(super) fn data_drop(
5736 store_modules: &AddrVec<ModuleAddr, ModuleInst>,
5737 store_data: &mut AddrVec<DataAddr, DataInst>,
5738 current_module: ModuleAddr,
5739 data_idx: usize,
5740) -> Result<(), RuntimeError> {
5741 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}