1use crate::{
2 assert_validated::UnwrapValidatedExt,
3 core::{
4 indices::{DataIdx, Idx, MemIdx},
5 reader::types::{memarg::MemArg, opcode},
6 utils::ToUsizeExt,
7 },
8 execution::interpreter_loop::{
9 calculate_mem_address, data_drop, define_instruction_fn, from_lanes, memory_init, to_lanes,
10 Args, InterpreterLoopOutcome,
11 },
12 value::{F32, F64},
13 Value,
14};
15use core::{array, num::NonZeroU64, ops::ControlFlow};
16
17define_instruction_fn! {
19 i32_load,
20 fuel_check = flat(opcode::I32_LOAD),
21 |Args {
22 store_inner,
23 modules,
24 resumable,
25 wasm,
26 current_module,
27 ..
28 }| {
29 let memarg = MemArg::read(wasm).unwrap_validated();
30 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
31
32 let module = unsafe { modules.get(*current_module) };
37
38 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
40 let mem_inst = unsafe { store_inner.memories.get(mem_addr) };
43
44 let idx = calculate_mem_address(&memarg, relative_address)?;
45 let data = mem_inst.mem.load(idx)?;
46
47 resumable.stack.push_value(Value::I32(data))?;
48 trace!("Instruction: i32.load [{relative_address}] -> [{data}]");
49 Ok(ControlFlow::Continue(()))
50 }
51}
52
53define_instruction_fn! {
54 i64_load,
55 fuel_check = flat(opcode::I64_LOAD),
56 |Args {
57 store_inner,
58 modules,
59 resumable,
60 wasm,
61 current_module,
62 ..
63 }| {
64 let memarg = MemArg::read(wasm).unwrap_validated();
65 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
66
67 let module = unsafe { modules.get(*current_module) };
72
73 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
75 let mem = unsafe { store_inner.memories.get(mem_addr) };
78
79 let idx = calculate_mem_address(&memarg, relative_address)?;
80 let data = mem.mem.load(idx)?;
81
82 resumable.stack.push_value(Value::I64(data))?;
83 trace!("Instruction: i64.load [{relative_address}] -> [{data}]");
84 Ok(ControlFlow::Continue(()))
85 }
86}
87
88define_instruction_fn! {
89 f32_load,
90 fuel_check = flat(opcode::F32_LOAD),
91 |Args {
92 store_inner,
93 modules,
94 resumable,
95 wasm,
96 current_module,
97 ..
98 }| {
99 let memarg = MemArg::read(wasm).unwrap_validated();
100 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
101
102 let module = unsafe { modules.get(*current_module) };
107
108 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
110 let mem = unsafe { store_inner.memories.get(mem_addr) };
113
114 let idx = calculate_mem_address(&memarg, relative_address)?;
115 let data = mem.mem.load(idx)?;
116
117 resumable.stack.push_value(Value::F32(data))?;
118 trace!("Instruction: f32.load [{relative_address}] -> [{data}]");
119 Ok(ControlFlow::Continue(()))
120 }
121}
122
123define_instruction_fn! {
124 f64_load,
125 fuel_check = flat(opcode::F64_LOAD),
126 |Args {
127 store_inner,
128 modules,
129 resumable,
130 wasm,
131 current_module,
132 ..
133 }| {
134 let memarg = MemArg::read(wasm).unwrap_validated();
135 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
136
137 let module = unsafe { modules.get(*current_module) };
142
143 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
145 let mem = unsafe { store_inner.memories.get(mem_addr) };
148
149 let idx = calculate_mem_address(&memarg, relative_address)?;
150 let data = mem.mem.load(idx)?;
151
152 resumable.stack.push_value(Value::F64(data))?;
153 trace!("Instruction: f64.load [{relative_address}] -> [{data}]");
154 Ok(ControlFlow::Continue(()))
155 }
156}
157
158define_instruction_fn! {
159 v128_load,
160 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD),
161 |Args {
162 wasm,
163 resumable,
164 modules,
165 current_module,
166 store_inner,
167 ..
168 }| {
169 let memarg = MemArg::read(wasm).unwrap_validated();
170 let module = unsafe { modules.get(*current_module) };
175
176 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
179 let memory = unsafe { store_inner.memories.get(mem_addr) };
183
184 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
185 let idx = calculate_mem_address(&memarg, relative_address)?;
186
187 let data: u128 = memory.mem.load(idx)?;
188 resumable.stack.push_value(data.to_le_bytes().into())?;
189 Ok(ControlFlow::Continue(()))
190 }
191}
192
193define_instruction_fn! {
195 i32_load8_s,
196 fuel_check = flat(opcode::I32_LOAD8_S),
197 |Args {
198 store_inner,
199 modules,
200 resumable,
201 wasm,
202 current_module,
203 ..
204 }| {
205 let memarg = MemArg::read(wasm).unwrap_validated();
206 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
207
208 let module = unsafe { modules.get(*current_module) };
213
214 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
216 let mem = unsafe { store_inner.memories.get(mem_addr) };
219
220 let idx = calculate_mem_address(&memarg, relative_address)?;
221 let data: i8 = mem.mem.load(idx)?;
222
223 resumable.stack.push_value(Value::I32(data as u32))?;
224 trace!("Instruction: i32.load8_s [{relative_address}] -> [{data}]");
225 Ok(ControlFlow::Continue(()))
226 }
227}
228
229define_instruction_fn! {
230 i32_load8_u,
231 fuel_check = flat(opcode::I32_LOAD8_U),
232 |Args {
233 store_inner,
234 modules,
235 resumable,
236 wasm,
237 current_module,
238 ..
239 }| {
240 let memarg = MemArg::read(wasm).unwrap_validated();
241 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
242
243 let module = unsafe { modules.get(*current_module) };
248
249 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
251 let mem = unsafe { store_inner.memories.get(mem_addr) };
254
255 let idx = calculate_mem_address(&memarg, relative_address)?;
256 let data: u8 = mem.mem.load(idx)?;
257
258 resumable.stack.push_value(Value::I32(data as u32))?;
259 trace!("Instruction: i32.load8_u [{relative_address}] -> [{data}]");
260 Ok(ControlFlow::Continue(()))
261 }
262}
263
264define_instruction_fn! {
265 i32_load16_s,
266 fuel_check = flat(opcode::I32_LOAD16_S),
267 |Args {
268 store_inner,
269 modules,
270 resumable,
271 wasm,
272 current_module,
273 ..
274 }| {
275 let memarg = MemArg::read(wasm).unwrap_validated();
276 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
277
278 let module = unsafe { modules.get(*current_module) };
283
284 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
286 let mem = unsafe { store_inner.memories.get(mem_addr) };
289
290 let idx = calculate_mem_address(&memarg, relative_address)?;
291 let data: i16 = mem.mem.load(idx)?;
292
293 resumable.stack.push_value(Value::I32(data as u32))?;
294 trace!("Instruction: i32.load16_s [{relative_address}] -> [{data}]");
295 Ok(ControlFlow::Continue(()))
296 }
297}
298
299define_instruction_fn! {
300 i32_load16_u,
301 fuel_check = flat(opcode::I32_LOAD16_U),
302 |Args {
303 store_inner,
304 modules,
305 resumable,
306 wasm,
307 current_module,
308 ..
309 }| {
310 let memarg = MemArg::read(wasm).unwrap_validated();
311 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
312
313 let module = unsafe { modules.get(*current_module) };
318
319 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
321 let mem = unsafe { store_inner.memories.get(mem_addr) };
324
325 let idx = calculate_mem_address(&memarg, relative_address)?;
326 let data: u16 = mem.mem.load(idx)?;
327
328 resumable.stack.push_value(Value::I32(data as u32))?;
329 trace!("Instruction: i32.load16_u [{relative_address}] -> [{data}]");
330 Ok(ControlFlow::Continue(()))
331 }
332}
333
334define_instruction_fn! {
335 i64_load8_s,
336 fuel_check = flat(opcode::I64_LOAD8_S),
337 |Args {
338 store_inner,
339 modules,
340 resumable,
341 wasm,
342 current_module,
343 ..
344 }| {
345 let memarg = MemArg::read(wasm).unwrap_validated();
346 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
347
348 let module = unsafe { modules.get(*current_module) };
353
354 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
356 let mem = unsafe { store_inner.memories.get(mem_addr) };
359
360 let idx = calculate_mem_address(&memarg, relative_address)?;
361 let data: i8 = mem.mem.load(idx)?;
362
363 resumable.stack.push_value(Value::I64(data as u64))?;
364 trace!("Instruction: i64.load8_s [{relative_address}] -> [{data}]");
365 Ok(ControlFlow::Continue(()))
366 }
367}
368
369define_instruction_fn! {
370 i64_load8_u,
371 fuel_check = flat(opcode::I64_LOAD8_U),
372 |Args {
373 store_inner,
374 modules,
375 resumable,
376 wasm,
377 current_module,
378 ..
379 }| {
380 let memarg = MemArg::read(wasm).unwrap_validated();
381 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
382
383 let module = unsafe { modules.get(*current_module) };
388
389 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
391 let mem = unsafe { store_inner.memories.get(mem_addr) };
394
395 let idx = calculate_mem_address(&memarg, relative_address)?;
396 let data: u8 = mem.mem.load(idx)?;
397
398 resumable.stack.push_value(Value::I64(data as u64))?;
399 trace!("Instruction: i64.load8_u [{relative_address}] -> [{data}]");
400 Ok(ControlFlow::Continue(()))
401 }
402}
403
404define_instruction_fn! {
405 i64_load16_s,
406 fuel_check = flat(opcode::I64_LOAD16_S),
407 |Args {
408 store_inner,
409 modules,
410 resumable,
411 wasm,
412 current_module,
413 ..
414 }| {
415 let memarg = MemArg::read(wasm).unwrap_validated();
416 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
417
418 let module = unsafe { modules.get(*current_module) };
423
424 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
426 let mem = unsafe { store_inner.memories.get(mem_addr) };
429
430 let idx = calculate_mem_address(&memarg, relative_address)?;
431 let data: i16 = mem.mem.load(idx)?;
432
433 resumable.stack.push_value(Value::I64(data as u64))?;
434 trace!("Instruction: i64.load16_s [{relative_address}] -> [{data}]");
435 Ok(ControlFlow::Continue(()))
436 }
437}
438
439define_instruction_fn! {
440 i64_load16_u,
441 fuel_check = flat(opcode::I64_LOAD16_U),
442 |Args {
443 store_inner,
444 modules,
445 resumable,
446 wasm,
447 current_module,
448 ..
449 }| {
450 let memarg = MemArg::read(wasm).unwrap_validated();
451 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
452
453 let module = unsafe { modules.get(*current_module) };
458
459 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
461 let mem = unsafe { store_inner.memories.get(mem_addr) };
464
465 let idx = calculate_mem_address(&memarg, relative_address)?;
466 let data: u16 = mem.mem.load(idx)?;
467
468 resumable.stack.push_value(Value::I64(data as u64))?;
469 trace!("Instruction: i64.load16_u [{relative_address}] -> [{data}]");
470 Ok(ControlFlow::Continue(()))
471 }
472}
473
474define_instruction_fn! {
475 i64_load32_s,
476 fuel_check = flat(opcode::I64_LOAD32_S),
477 |Args {
478 store_inner,
479 modules,
480 resumable,
481 wasm,
482 current_module,
483 ..
484 }| {
485 let memarg = MemArg::read(wasm).unwrap_validated();
486 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
487
488 let module = unsafe { modules.get(*current_module) };
493
494 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
496 let mem = unsafe { store_inner.memories.get(mem_addr) };
499
500 let idx = calculate_mem_address(&memarg, relative_address)?;
501 let data: i32 = mem.mem.load(idx)?;
502
503 resumable.stack.push_value(Value::I64(data as u64))?;
504 trace!("Instruction: i64.load32_s [{relative_address}] -> [{data}]");
505 Ok(ControlFlow::Continue(()))
506 }
507}
508
509define_instruction_fn! {
510 i64_load32_u,
511 fuel_check = flat(opcode::I64_LOAD32_U),
512 |Args {
513 store_inner,
514 modules,
515 resumable,
516 wasm,
517 current_module,
518 ..
519 }| {
520 let memarg = MemArg::read(wasm).unwrap_validated();
521 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
522
523 let module = unsafe { modules.get(*current_module) };
528
529 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
531 let mem = unsafe { store_inner.memories.get(mem_addr) };
534
535 let idx = calculate_mem_address(&memarg, relative_address)?;
536 let data: u32 = mem.mem.load(idx)?;
537
538 resumable.stack.push_value(Value::I64(data as u64))?;
539 trace!("Instruction: i64.load32_u [{relative_address}] -> [{data}]");
540 Ok(ControlFlow::Continue(()))
541 }
542}
543
544define_instruction_fn! {
546 v128_load8x8_s,
547 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD8X8_S),
548 |Args {
549 wasm,
550 resumable,
551 modules,
552 current_module,
553 store_inner,
554 ..
555 }| {
556 let memarg = MemArg::read(wasm).unwrap_validated();
557 let module = unsafe { modules.get(*current_module) };
562
563 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
566 let memory = unsafe { store_inner.memories.get(mem_addr) };
570
571 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
572 let idx = calculate_mem_address(&memarg, relative_address)?;
573
574 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));
578 let half_lanes: [i8; 8] = to_lanes::<1, 16, i8>(data)[..8].try_into().unwrap();
579
580 let extended_lanes = half_lanes.map(|lane| lane as i16);
581
582 resumable
583 .stack
584 .push_value(Value::V128(from_lanes(extended_lanes)))?;
585 Ok(ControlFlow::Continue(()))
586 }
587}
588define_instruction_fn! {
589 v128_load8x8_u,
590 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD8X8_U),
591 |Args {
592 wasm,
593 resumable,
594 modules,
595 current_module,
596 store_inner,
597 ..
598 }| {
599 let memarg = MemArg::read(wasm).unwrap_validated();
600 let module = unsafe { modules.get(*current_module) };
605
606 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
609 let memory = unsafe { store_inner.memories.get(mem_addr) };
613
614 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
615 let idx = calculate_mem_address(&memarg, relative_address)?;
616
617 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));
621 let half_lanes: [u8; 8] = to_lanes::<1, 16, u8>(data)[..8].try_into().unwrap();
622
623 let extended_lanes = half_lanes.map(|lane| lane as u16);
624
625 resumable
626 .stack
627 .push_value(Value::V128(from_lanes(extended_lanes)))?;
628 Ok(ControlFlow::Continue(()))
629 }
630}
631define_instruction_fn! {
632 v128_load16x4_s,
633 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD16X4_S),
634 |Args {
635 wasm,
636 resumable,
637 modules,
638 current_module,
639 store_inner,
640 ..
641 }| {
642 let memarg = MemArg::read(wasm).unwrap_validated();
643 let module = unsafe { modules.get(*current_module) };
648
649 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
652 let memory = unsafe { store_inner.memories.get(mem_addr) };
656
657 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
658 let idx = calculate_mem_address(&memarg, relative_address)?;
659
660 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));
664 let half_lanes: [i16; 4] = to_lanes::<2, 8, i16>(data)[..4].try_into().unwrap();
665
666 let extended_lanes = half_lanes.map(|lane| lane as i32);
667
668 resumable
669 .stack
670 .push_value(Value::V128(from_lanes(extended_lanes)))?;
671 Ok(ControlFlow::Continue(()))
672 }
673}
674define_instruction_fn! {
675 v128_load16x4_u,
676 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD16X4_U),
677 |Args {
678 wasm,
679 resumable,
680 modules,
681 current_module,
682 store_inner,
683 ..
684 }| {
685 let memarg = MemArg::read(wasm).unwrap_validated();
686 let module = unsafe { modules.get(*current_module) };
691
692 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
695 let memory = unsafe { store_inner.memories.get(mem_addr) };
699
700 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
701 let idx = calculate_mem_address(&memarg, relative_address)?;
702
703 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));
707 let half_lanes: [u16; 4] = to_lanes::<2, 8, u16>(data)[..4].try_into().unwrap();
708
709 let extended_lanes = half_lanes.map(|lane| lane as u32);
710
711 resumable
712 .stack
713 .push_value(Value::V128(from_lanes(extended_lanes)))?;
714 Ok(ControlFlow::Continue(()))
715 }
716}
717define_instruction_fn! {
718 v128_load32x2_s,
719 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD32X2_S),
720 |Args {
721 wasm,
722 resumable,
723 modules,
724 current_module,
725 store_inner,
726 ..
727 }| {
728 let memarg = MemArg::read(wasm).unwrap_validated();
729 let module = unsafe { modules.get(*current_module) };
734
735 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
738 let memory = unsafe { store_inner.memories.get(mem_addr) };
742
743 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
744 let idx = calculate_mem_address(&memarg, relative_address)?;
745
746 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));
750 let half_lanes: [i32; 2] = to_lanes::<4, 4, i32>(data)[..2].try_into().unwrap();
751
752 let extended_lanes = half_lanes.map(|lane| lane as i64);
753
754 resumable
755 .stack
756 .push_value(Value::V128(from_lanes(extended_lanes)))?;
757 Ok(ControlFlow::Continue(()))
758 }
759}
760define_instruction_fn! {
761 v128_load32x2_u,
762 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD32X2_U),
763 |Args {
764 wasm,
765 resumable,
766 modules,
767 current_module,
768 store_inner,
769 ..
770 }| {
771 let memarg = MemArg::read(wasm).unwrap_validated();
772 let module = unsafe { modules.get(*current_module) };
777
778 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
781 let memory = unsafe { store_inner.memories.get(mem_addr) };
785
786 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
787 let idx = calculate_mem_address(&memarg, relative_address)?;
788
789 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));
793 let half_lanes: [u32; 2] = to_lanes::<4, 4, u32>(data)[..2].try_into().unwrap();
794
795 let extended_lanes = half_lanes.map(|lane| lane as u64);
796
797 resumable
798 .stack
799 .push_value(Value::V128(from_lanes(extended_lanes)))?;
800 Ok(ControlFlow::Continue(()))
801 }
802}
803
804define_instruction_fn! {
806 v128_load8_splat,
807 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD8_SPLAT),
808 |Args {
809 wasm,
810 resumable,
811 modules,
812 current_module,
813 store_inner,
814 ..
815 }| {
816 let memarg = MemArg::read(wasm).unwrap_validated();
817 let module = unsafe { modules.get(*current_module) };
822
823 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
826 let memory = unsafe { store_inner.memories.get(mem_addr) };
830 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
831 let idx = calculate_mem_address(&memarg, relative_address)?;
832
833 let lane = memory.mem.load::<1, u8>(idx)?;
834 resumable
835 .stack
836 .push_value(Value::V128(from_lanes([lane; 16])))?;
837 Ok(ControlFlow::Continue(()))
838 }
839}
840define_instruction_fn! {
841 v128_load16_splat,
842 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD16_SPLAT),
843 |Args {
844 wasm,
845 resumable,
846 modules,
847 current_module,
848 store_inner,
849 ..
850 }| {
851 let memarg = MemArg::read(wasm).unwrap_validated();
852 let module = unsafe { modules.get(*current_module) };
857
858 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
861 let memory = unsafe { store_inner.memories.get(mem_addr) };
865 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
866 let idx = calculate_mem_address(&memarg, relative_address)?;
867
868 let lane = memory.mem.load::<2, u16>(idx)?;
869 resumable
870 .stack
871 .push_value(Value::V128(from_lanes([lane; 8])))?;
872 Ok(ControlFlow::Continue(()))
873 }
874}
875define_instruction_fn! {
876 v128_load32_splat,
877 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD32_SPLAT),
878 |Args {
879 wasm,
880 resumable,
881 modules,
882 current_module,
883 store_inner,
884 ..
885 }| {
886 let memarg = MemArg::read(wasm).unwrap_validated();
887 let module = unsafe { modules.get(*current_module) };
892
893 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
896 let memory = unsafe { store_inner.memories.get(mem_addr) };
900 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
901 let idx = calculate_mem_address(&memarg, relative_address)?;
902
903 let lane = memory.mem.load::<4, u32>(idx)?;
904 resumable
905 .stack
906 .push_value(Value::V128(from_lanes([lane; 4])))?;
907 Ok(ControlFlow::Continue(()))
908 }
909}
910define_instruction_fn! {
911 v128_load64_splat,
912 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD64_SPLAT),
913 |Args {
914 wasm,
915 resumable,
916 modules,
917 current_module,
918 store_inner,
919 ..
920 }| {
921 let memarg = MemArg::read(wasm).unwrap_validated();
922 let module = unsafe { modules.get(*current_module) };
927
928 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
931 let memory = unsafe { store_inner.memories.get(mem_addr) };
935 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
936 let idx = calculate_mem_address(&memarg, relative_address)?;
937
938 let lane = memory.mem.load::<8, u64>(idx)?;
939 resumable
940 .stack
941 .push_value(Value::V128(from_lanes([lane; 2])))?;
942 Ok(ControlFlow::Continue(()))
943 }
944}
945
946define_instruction_fn! {
948 v128_load32_zero,
949 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD32_ZERO),
950 |Args {
951 wasm,
952 resumable,
953 modules,
954 current_module,
955 store_inner,
956 ..
957 }| {
958 let memarg = MemArg::read(wasm).unwrap_validated();
959
960 let module = unsafe { modules.get(*current_module) };
965
966 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
969 let memory = unsafe { store_inner.memories.get(mem_addr) };
973
974 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
975 let idx = calculate_mem_address(&memarg, relative_address)?;
976
977 let data = memory.mem.load::<4, u32>(idx)? as u128;
978 resumable
979 .stack
980 .push_value(Value::V128(data.to_le_bytes()))?;
981 Ok(ControlFlow::Continue(()))
982 }
983}
984define_instruction_fn! {
985 v128_load64_zero,
986 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD64_ZERO),
987 |Args {
988 wasm,
989 resumable,
990 modules,
991 current_module,
992 store_inner,
993 ..
994 }| {
995 let memarg = MemArg::read(wasm).unwrap_validated();
996 let module = unsafe { modules.get(*current_module) };
1001
1002 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1005 let memory = unsafe { store_inner.memories.get(mem_addr) };
1009
1010 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1011 let idx = calculate_mem_address(&memarg, relative_address)?;
1012
1013 let data = memory.mem.load::<8, u64>(idx)? as u128;
1014 resumable
1015 .stack
1016 .push_value(Value::V128(data.to_le_bytes()))?;
1017 Ok(ControlFlow::Continue(()))
1018 }
1019}
1020
1021define_instruction_fn! {
1023 v128_load8_lane,
1024 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD8_LANE),
1025 |Args {
1026 wasm,
1027 resumable,
1028 modules,
1029 current_module,
1030 store_inner,
1031 ..
1032 }| {
1033 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1034 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1035 let memarg = MemArg::read(wasm).unwrap_validated();
1036 let module = unsafe { modules.get(*current_module) };
1041
1042 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1045 let memory = unsafe { store_inner.memories.get(mem_addr) };
1049 let idx = calculate_mem_address(&memarg, relative_address)?;
1050 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1051 let mut lanes: [u8; 16] = to_lanes(data);
1052 *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<1, u8>(idx)?;
1053 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
1054 Ok(ControlFlow::Continue(()))
1055 }
1056}
1057
1058define_instruction_fn! {
1059 v128_load16_lane,
1060 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD16_LANE),
1061 |Args {
1062 wasm,
1063 resumable,
1064 modules,
1065 current_module,
1066 store_inner,
1067 ..
1068 }| {
1069 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1070 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1071 let memarg = MemArg::read(wasm).unwrap_validated();
1072 let module = unsafe { modules.get(*current_module) };
1077
1078 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1081 let memory = unsafe { store_inner.memories.get(mem_addr) };
1085 let idx = calculate_mem_address(&memarg, relative_address)?;
1086 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1087 let mut lanes: [u16; 8] = to_lanes(data);
1088 *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<2, u16>(idx)?;
1089 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
1090 Ok(ControlFlow::Continue(()))
1091 }
1092}
1093define_instruction_fn! {
1094 v128_load32_lane,
1095 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD32_LANE),
1096 |Args {
1097 wasm,
1098 resumable,
1099 modules,
1100 current_module,
1101 store_inner,
1102 ..
1103 }| {
1104 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1105 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1106 let memarg = MemArg::read(wasm).unwrap_validated();
1107 let module = unsafe { modules.get(*current_module) };
1112
1113 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1116 let memory = unsafe { store_inner.memories.get(mem_addr) };
1120 let idx = calculate_mem_address(&memarg, relative_address)?;
1121 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1122 let mut lanes: [u32; 4] = to_lanes(data);
1123 *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<4, u32>(idx)?;
1124 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
1125 Ok(ControlFlow::Continue(()))
1126 }
1127}
1128define_instruction_fn! {
1129 v128_load64_lane,
1130 fuel_check = flat_fd(opcode::fd_extensions::V128_LOAD64_LANE),
1131 |Args {
1132 wasm,
1133 resumable,
1134 modules,
1135 current_module,
1136 store_inner,
1137 ..
1138 }| {
1139 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1140 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1141 let memarg = MemArg::read(wasm).unwrap_validated();
1142 let module = unsafe { modules.get(*current_module) };
1147
1148 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1151 let memory = unsafe { store_inner.memories.get(mem_addr) };
1155 let idx = calculate_mem_address(&memarg, relative_address)?;
1156 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1157 let mut lanes: [u64; 2] = to_lanes(data);
1158 *lanes.get_mut(lane_idx).unwrap_validated() = memory.mem.load::<8, u64>(idx)?;
1159 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
1160 Ok(ControlFlow::Continue(()))
1161 }
1162}
1163
1164define_instruction_fn! {
1166 i32_store,
1167 fuel_check = flat(opcode::I32_STORE),
1168 |Args {
1169 store_inner,
1170 modules,
1171 resumable,
1172 wasm,
1173 current_module,
1174 ..
1175 }| {
1176 let memarg = MemArg::read(wasm).unwrap_validated();
1177
1178 let data_to_store: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1179 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1180
1181 let module = unsafe { modules.get(*current_module) };
1186
1187 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1189 let mem = unsafe { store_inner.memories.get(mem_addr) };
1192
1193 let idx = calculate_mem_address(&memarg, relative_address)?;
1194 mem.mem.store(idx, data_to_store)?;
1195
1196 trace!("Instruction: i32.store [{relative_address} {data_to_store}] -> []");
1197 Ok(ControlFlow::Continue(()))
1198 }
1199}
1200
1201define_instruction_fn! {
1202 i64_store,
1203 fuel_check = flat(opcode::I64_STORE),
1204 |Args {
1205 store_inner,
1206 modules,
1207 resumable,
1208 wasm,
1209 current_module,
1210 ..
1211 }| {
1212 let memarg = MemArg::read(wasm).unwrap_validated();
1213
1214 let data_to_store: u64 = resumable.stack.pop_value().try_into().unwrap_validated();
1215 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1216
1217 let module = unsafe { modules.get(*current_module) };
1222
1223 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1225 let mem = unsafe { store_inner.memories.get(mem_addr) };
1228
1229 let idx = calculate_mem_address(&memarg, relative_address)?;
1230 mem.mem.store(idx, data_to_store)?;
1231
1232 trace!("Instruction: i64.store [{relative_address} {data_to_store}] -> []");
1233 Ok(ControlFlow::Continue(()))
1234 }
1235}
1236
1237define_instruction_fn! {
1238 f32_store,
1239 fuel_check = flat(opcode::F32_STORE),
1240 |Args {
1241 store_inner,
1242 modules,
1243 resumable,
1244 wasm,
1245 current_module,
1246 ..
1247 }| {
1248 let memarg = MemArg::read(wasm).unwrap_validated();
1249
1250 let data_to_store: F32 = resumable.stack.pop_value().try_into().unwrap_validated();
1251 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1252
1253 let module = unsafe { modules.get(*current_module) };
1258
1259 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1261 let mem = unsafe { store_inner.memories.get(mem_addr) };
1264
1265 let idx = calculate_mem_address(&memarg, relative_address)?;
1266 mem.mem.store(idx, data_to_store)?;
1267
1268 trace!("Instruction: f32.store [{relative_address} {data_to_store}] -> []");
1269 Ok(ControlFlow::Continue(()))
1270 }
1271}
1272
1273define_instruction_fn! {
1274 f64_store,
1275 fuel_check = flat(opcode::F64_STORE),
1276 |Args {
1277 store_inner,
1278 modules,
1279 resumable,
1280 wasm,
1281 current_module,
1282 ..
1283 }| {
1284 let memarg = MemArg::read(wasm).unwrap_validated();
1285
1286 let data_to_store: F64 = resumable.stack.pop_value().try_into().unwrap_validated();
1287 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1288
1289 let module = unsafe { modules.get(*current_module) };
1294
1295 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1297 let mem = unsafe { store_inner.memories.get(mem_addr) };
1300
1301 let idx = calculate_mem_address(&memarg, relative_address)?;
1302 mem.mem.store(idx, data_to_store)?;
1303
1304 trace!("Instruction: f64.store [{relative_address} {data_to_store}] -> []");
1305 Ok(ControlFlow::Continue(()))
1306 }
1307}
1308
1309define_instruction_fn! {
1310 v128_store,
1311 fuel_check = flat_fd(opcode::fd_extensions::V128_STORE),
1312 |Args {
1313 wasm,
1314 resumable,
1315 modules,
1316 current_module,
1317 store_inner,
1318 ..
1319 }| {
1320 let memarg = MemArg::read(wasm).unwrap_validated();
1321 let module = unsafe { modules.get(*current_module) };
1326
1327 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1330 let memory = unsafe { store_inner.memories.get(mem_addr) };
1334
1335 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1336 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1337 let idx = calculate_mem_address(&memarg, relative_address)?;
1338
1339 memory.mem.store(idx, u128::from_le_bytes(data))?;
1340 Ok(ControlFlow::Continue(()))
1341 }
1342}
1343
1344define_instruction_fn! {
1346 i32_store8,
1347 fuel_check = flat(opcode::I32_STORE8),
1348 |Args {
1349 store_inner,
1350 modules,
1351 resumable,
1352 wasm,
1353 current_module,
1354 ..
1355 }| {
1356 let memarg = MemArg::read(wasm).unwrap_validated();
1357
1358 let data_to_store: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1359 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1360
1361 let wrapped_data = data_to_store as i8;
1362
1363 let module = unsafe { modules.get(*current_module) };
1368
1369 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1371 let mem = unsafe { store_inner.memories.get(mem_addr) };
1374
1375 let idx = calculate_mem_address(&memarg, relative_address)?;
1376 mem.mem.store(idx, wrapped_data)?;
1377
1378 trace!("Instruction: i32.store8 [{relative_address} {wrapped_data}] -> []");
1379 Ok(ControlFlow::Continue(()))
1380 }
1381}
1382
1383define_instruction_fn! {
1384 i32_store16,
1385 fuel_check = flat(opcode::I32_STORE16),
1386 |Args {
1387 store_inner,
1388 modules,
1389 resumable,
1390 wasm,
1391 current_module,
1392 ..
1393 }| {
1394 let memarg = MemArg::read(wasm).unwrap_validated();
1395
1396 let data_to_store: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1397 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1398
1399 let wrapped_data = data_to_store as i16;
1400
1401 let module = unsafe { modules.get(*current_module) };
1406
1407 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1409 let mem = unsafe { store_inner.memories.get(mem_addr) };
1412
1413 let idx = calculate_mem_address(&memarg, relative_address)?;
1414 mem.mem.store(idx, wrapped_data)?;
1415
1416 trace!("Instruction: i32.store16 [{relative_address} {data_to_store}] -> []");
1417 Ok(ControlFlow::Continue(()))
1418 }
1419}
1420
1421define_instruction_fn! {
1422 i64_store8,
1423 fuel_check = flat(opcode::I64_STORE8),
1424 |Args {
1425 store_inner,
1426 modules,
1427 resumable,
1428 wasm,
1429 current_module,
1430 ..
1431 }| {
1432 let memarg = MemArg::read(wasm).unwrap_validated();
1433
1434 let data_to_store: i64 = resumable.stack.pop_value().try_into().unwrap_validated();
1435 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1436
1437 let wrapped_data = data_to_store as i8;
1438
1439 let module = unsafe { modules.get(*current_module) };
1444
1445 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1447 let mem = unsafe { store_inner.memories.get(mem_addr) };
1450
1451 let idx = calculate_mem_address(&memarg, relative_address)?;
1452 mem.mem.store(idx, wrapped_data)?;
1453
1454 trace!("Instruction: i64.store8 [{relative_address} {data_to_store}] -> []");
1455 Ok(ControlFlow::Continue(()))
1456 }
1457}
1458
1459define_instruction_fn! {
1460 i64_store16,
1461 fuel_check = flat(opcode::I64_STORE16),
1462 |Args {
1463 store_inner,
1464 modules,
1465 resumable,
1466 wasm,
1467 current_module,
1468 ..
1469 }| {
1470 let memarg = MemArg::read(wasm).unwrap_validated();
1471
1472 let data_to_store: i64 = resumable.stack.pop_value().try_into().unwrap_validated();
1473 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1474
1475 let wrapped_data = data_to_store as i16;
1476
1477 let module = unsafe { modules.get(*current_module) };
1482
1483 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1485 let mem = unsafe { store_inner.memories.get(mem_addr) };
1488
1489 let idx = calculate_mem_address(&memarg, relative_address)?;
1490 mem.mem.store(idx, wrapped_data)?;
1491
1492 trace!("Instruction: i64.store16 [{relative_address} {data_to_store}] -> []");
1493 Ok(ControlFlow::Continue(()))
1494 }
1495}
1496
1497define_instruction_fn! {
1498 i64_store32,
1499 fuel_check = flat(opcode::I64_STORE32),
1500 |Args {
1501 store_inner,
1502 modules,
1503 resumable,
1504 wasm,
1505 current_module,
1506 ..
1507 }| {
1508 let memarg = MemArg::read(wasm).unwrap_validated();
1509
1510 let data_to_store: i64 = resumable.stack.pop_value().try_into().unwrap_validated();
1511 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1512
1513 let wrapped_data = data_to_store as i32;
1514
1515 let module = unsafe { modules.get(*current_module) };
1520
1521 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1523 let mem = unsafe { store_inner.memories.get(mem_addr) };
1526
1527 let idx = calculate_mem_address(&memarg, relative_address)?;
1528 mem.mem.store(idx, wrapped_data)?;
1529
1530 trace!("Instruction: i64.store32 [{relative_address} {data_to_store}] -> []");
1531 Ok(ControlFlow::Continue(()))
1532 }
1533}
1534
1535define_instruction_fn! {
1537 v128_store8_lane,
1538 fuel_check = flat_fd(opcode::fd_extensions::V128_STORE8_LANE),
1539 |Args {
1540 wasm,
1541 resumable,
1542 modules,
1543 current_module,
1544 store_inner,
1545 ..
1546 }| {
1547 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1548 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1549 let memarg = MemArg::read(wasm).unwrap_validated();
1550 let module = unsafe { modules.get(*current_module) };
1555
1556 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1559 let memory = unsafe { store_inner.memories.get(mem_addr) };
1563 let idx = calculate_mem_address(&memarg, relative_address)?;
1564 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1565
1566 let lane = *to_lanes::<1, 16, u8>(data).get(lane_idx).unwrap_validated();
1567
1568 memory.mem.store::<1, u8>(idx, lane)?;
1569 Ok(ControlFlow::Continue(()))
1570 }
1571}
1572define_instruction_fn! {
1573 v128_store16_lane,
1574 fuel_check = flat_fd(opcode::fd_extensions::V128_STORE16_LANE),
1575 |Args {
1576 wasm,
1577 resumable,
1578 modules,
1579 current_module,
1580 store_inner,
1581 ..
1582 }| {
1583 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1584 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1585 let memarg = MemArg::read(wasm).unwrap_validated();
1586 let module = unsafe { modules.get(*current_module) };
1591
1592 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1595 let memory = unsafe { store_inner.memories.get(mem_addr) };
1599 let idx = calculate_mem_address(&memarg, relative_address)?;
1600 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1601
1602 let lane = *to_lanes::<2, 8, u16>(data).get(lane_idx).unwrap_validated();
1603
1604 memory.mem.store::<2, u16>(idx, lane)?;
1605 Ok(ControlFlow::Continue(()))
1606 }
1607}
1608define_instruction_fn! {
1609 v128_store32_lane,
1610 fuel_check = flat_fd(opcode::fd_extensions::V128_STORE32_LANE),
1611 |Args {
1612 wasm,
1613 resumable,
1614 modules,
1615 current_module,
1616 store_inner,
1617 ..
1618 }| {
1619 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1620 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1621 let memarg = MemArg::read(wasm).unwrap_validated();
1622 let module = unsafe { modules.get(*current_module) };
1627
1628 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1631 let memory = unsafe { store_inner.memories.get(mem_addr) };
1635 let idx = calculate_mem_address(&memarg, relative_address)?;
1636 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1637
1638 let lane = *to_lanes::<4, 4, u32>(data).get(lane_idx).unwrap_validated();
1639
1640 memory.mem.store::<4, u32>(idx, lane)?;
1641 Ok(ControlFlow::Continue(()))
1642 }
1643}
1644define_instruction_fn! {
1645 v128_store64_lane,
1646 fuel_check = flat_fd(opcode::fd_extensions::V128_STORE64_LANE),
1647 |Args {
1648 wasm,
1649 resumable,
1650 modules,
1651 current_module,
1652 store_inner,
1653 ..
1654 }| {
1655 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1656 let relative_address: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1657 let memarg = MemArg::read(wasm).unwrap_validated();
1658 let module = unsafe { modules.get(*current_module) };
1663
1664 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1667 let memory = unsafe { store_inner.memories.get(mem_addr) };
1671 let idx = calculate_mem_address(&memarg, relative_address)?;
1672 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
1673
1674 let lane = *to_lanes::<8, 2, u64>(data).get(lane_idx).unwrap_validated();
1675
1676 memory.mem.store::<8, u64>(idx, lane)?;
1677 Ok(ControlFlow::Continue(()))
1678 }
1679}
1680
1681define_instruction_fn! {
1683 memory_size,
1684 fuel_check = flat(opcode::MEMORY_SIZE),
1685 |Args {
1686 store_inner,
1687 modules,
1688 resumable,
1689 wasm,
1690 current_module,
1691 ..
1692 }| {
1693 let _zero = wasm.read_u8().unwrap_validated();
1696 let module = unsafe { modules.get(*current_module) };
1701
1702 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1704 let mem = unsafe { store_inner.memories.get(mem_addr) };
1707 let size = mem.size() as u32;
1708 resumable.stack.push_value(Value::I32(size))?;
1709 trace!("Instruction: memory.size [] -> [{}]", size);
1710 Ok(ControlFlow::Continue(()))
1711 }
1712}
1713
1714define_instruction_fn! {
1716 memory_grow,
1717 fuel_check = omit,
1718 |Args {
1719 store_inner,
1720 modules,
1721 resumable,
1722 wasm,
1723 current_module,
1724 ..
1725 }| {
1726 let _zero = wasm.read_u8().unwrap_validated();
1729 let module = unsafe { modules.get(*current_module) };
1734
1735 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1737 let mem = unsafe { store_inner.memories.get_mut(mem_addr) };
1740
1741 let sz: u32 = mem.size() as u32;
1742
1743 let n: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1744 let cost = T::get_flat_cost(opcode::MEMORY_GROW)
1746 + u64::from(n) * T::get_cost_per_element(opcode::MEMORY_GROW);
1747 if let Some(fuel) = &mut resumable.maybe_fuel {
1748 if *fuel >= cost {
1749 *fuel -= cost;
1750 } else {
1751 resumable.stack.push_value(Value::I32(n)).unwrap_validated(); return Ok(ControlFlow::Break(InterpreterLoopOutcome::OutOfFuel {
1754 required_fuel: NonZeroU64::new(cost - *fuel).expect(
1755 "the last check guarantees that the current fuel is smaller than cost",
1756 ),
1757 }));
1758 }
1759 }
1760
1761 let pushed_value = match mem.grow(n) {
1765 Ok(_) => sz,
1766 Err(_) => u32::MAX,
1767 };
1768 resumable.stack.push_value(Value::I32(pushed_value))?;
1769 trace!("Instruction: memory.grow [{}] -> [{}]", n, pushed_value);
1770 Ok(ControlFlow::Continue(()))
1771 }
1772}
1773
1774define_instruction_fn! {
1777 memory_fill,
1778 fuel_check = omit,
1779 |Args {
1780 resumable,
1781 wasm,
1782 store_inner,
1783 modules,
1784 current_module,
1785 ..
1786 }| {
1787 let _zero = wasm.read_u8().unwrap_validated();
1795
1796 let module = unsafe { modules.get(*current_module) };
1801
1802 let mem_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1804 let mem = unsafe { store_inner.memories.get(mem_addr) };
1808
1809 let n: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1810 let cost = T::get_fc_extension_flat_cost(opcode::fc_extensions::MEMORY_FILL)
1812 + u64::from(n)
1813 * T::get_fc_extension_cost_per_element(opcode::fc_extensions::MEMORY_FILL);
1814 if let Some(fuel) = &mut resumable.maybe_fuel {
1815 if *fuel >= cost {
1816 *fuel -= cost;
1817 } else {
1818 resumable.stack.push_value(Value::I32(n)).unwrap_validated(); return Ok(ControlFlow::Break(InterpreterLoopOutcome::OutOfFuel {
1820 required_fuel: NonZeroU64::new(cost - *fuel).expect(
1821 "the last check guarantees that the current fuel is smaller than cost",
1822 ),
1823 }));
1824 }
1825 }
1826
1827 let val: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1828
1829 if !(0..=255).contains(&val) {
1830 warn!("Value for memory.fill does not fit in a byte ({val})");
1831 }
1832
1833 let d: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1834
1835 mem.mem
1836 .fill(d.cast_unsigned().into_usize(), val as u8, n.into_usize())?;
1837
1838 trace!("Instruction: memory.fill");
1839 Ok(ControlFlow::Continue(()))
1840 }
1841}
1842
1843define_instruction_fn! {
1846 memory_copy,
1847 fuel_check = omit,
1848 |Args {
1849 resumable,
1850 wasm,
1851 store_inner,
1852 modules,
1853 current_module,
1854 ..
1855 }| {
1856 let _zero = wasm.read_u8().unwrap_validated();
1863 let _zero = wasm.read_u8().unwrap_validated();
1864
1865 let module = unsafe { modules.get(*current_module) };
1870
1871 let src_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1874 let dst_addr = *unsafe { module.mem_addrs.get(MemIdx::new(0)) };
1877
1878 let n: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1879 let cost = T::get_fc_extension_flat_cost(opcode::fc_extensions::MEMORY_COPY)
1881 + u64::from(n)
1882 * T::get_fc_extension_cost_per_element(opcode::fc_extensions::MEMORY_COPY);
1883 if let Some(fuel) = &mut resumable.maybe_fuel {
1884 if *fuel >= cost {
1885 *fuel -= cost;
1886 } else {
1887 resumable.stack.push_value(Value::I32(n)).unwrap_validated(); return Ok(ControlFlow::Break(InterpreterLoopOutcome::OutOfFuel {
1889 required_fuel: NonZeroU64::new(cost - *fuel).expect(
1890 "the last check guarantees that the current fuel is smaller than cost",
1891 ),
1892 }));
1893 }
1894 }
1895
1896 let s: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1897 let d: i32 = resumable.stack.pop_value().try_into().unwrap_validated();
1898
1899 let src_mem = unsafe { store_inner.memories.get(src_addr) };
1903 let dest_mem = unsafe { store_inner.memories.get(dst_addr) };
1907
1908 dest_mem.mem.copy(
1909 d.cast_unsigned().into_usize(),
1910 &src_mem.mem,
1911 s.cast_unsigned().into_usize(),
1912 n.into_usize(),
1913 )?;
1914 trace!("Instruction: memory.copy");
1915 Ok(ControlFlow::Continue(()))
1916 }
1917}
1918
1919define_instruction_fn! {
1923 memory_init_fn,
1924 fuel_check = omit,
1925 |Args {
1926 wasm,
1927 resumable,
1928 modules,
1929 current_module,
1930 store_inner,
1931 ..
1932 }| {
1933 let data_idx = unsafe { DataIdx::read_unchecked(wasm) };
1940
1941 let _zero = wasm.read_u8().unwrap_validated();
1944
1945 let n: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1946 let cost = T::get_fc_extension_flat_cost(opcode::fc_extensions::MEMORY_INIT)
1948 + u64::from(n)
1949 * T::get_fc_extension_cost_per_element(opcode::fc_extensions::MEMORY_INIT);
1950 if let Some(fuel) = &mut resumable.maybe_fuel {
1951 if *fuel >= cost {
1952 *fuel -= cost;
1953 } else {
1954 resumable.stack.push_value(Value::I32(n)).unwrap_validated(); return Ok(ControlFlow::Break(InterpreterLoopOutcome::OutOfFuel {
1956 required_fuel: NonZeroU64::new(cost - *fuel).expect(
1957 "the last check guarantees that the current fuel is smaller than cost",
1958 ),
1959 }));
1960 }
1961 }
1962
1963 let s: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1964 let d: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
1965
1966 unsafe {
1980 memory_init(
1981 modules,
1982 &mut store_inner.memories,
1983 &store_inner.data,
1984 *current_module,
1985 data_idx,
1986 MemIdx::new(0),
1987 n,
1988 s,
1989 d,
1990 )?
1991 };
1992 Ok(ControlFlow::Continue(()))
1993 }
1994}
1995
1996define_instruction_fn! {
1998 data_drop_fn,
1999 fuel_check = flat_fc(opcode::fc_extensions::DATA_DROP),
2000 |Args {
2001 wasm,
2002 modules,
2003 current_module,
2004 store_inner,
2005 ..
2006 }| {
2007 let data_idx = unsafe { DataIdx::read_unchecked(wasm) };
2010 unsafe { data_drop(modules, &mut store_inner.data, *current_module, data_idx) };
2023 Ok(ControlFlow::Continue(()))
2024 }
2025}