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