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