1use core::{
2 array,
3 ops::{Add, ControlFlow, Div, Mul, Neg, Sub},
4};
5
6use crate::{
7 assert_validated::UnwrapValidatedExt,
8 core::reader::types::opcode,
9 execution::interpreter_loop::{define_instruction_fn, from_lanes, to_lanes, Args},
10 value::{F32, F64},
11 Value,
12};
13
14define_instruction_fn! {
16 v128_const,
17 fuel_check = flat_fd(opcode::fd_extensions::V128_CONST),
18 |Args {
19 wasm, resumable, ..
20 }| {
21 let mut data = [0; 16];
22 for byte_ref in &mut data {
23 *byte_ref = wasm.read_u8().unwrap_validated();
24 }
25
26 resumable.stack.push_value(Value::V128(data))?;
27 Ok(ControlFlow::Continue(()))
28 }
29}
30
31define_instruction_fn! {
33 v128_not,
34 fuel_check = flat_fd(opcode::fd_extensions::V128_NOT),
35 |Args { resumable, .. }| {
36 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
37 resumable
38 .stack
39 .push_value(Value::V128(data.map(|byte| !byte)))?;
40 Ok(ControlFlow::Continue(()))
41 }
42}
43
44define_instruction_fn! {
46 v128_and,
47 fuel_check = flat_fd(opcode::fd_extensions::V128_AND),
48 |Args { resumable, .. }| {
49 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
50 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
51 let result = array::from_fn(|i| data1[i] & data2[i]);
52 resumable.stack.push_value(Value::V128(result))?;
53 Ok(ControlFlow::Continue(()))
54 }
55}
56define_instruction_fn! {
57 v128_andnot,
58 fuel_check = flat_fd(opcode::fd_extensions::V128_ANDNOT),
59 |Args { resumable, .. }| {
60 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
61 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
62 let result = array::from_fn(|i| data1[i] & !data2[i]);
63 resumable.stack.push_value(Value::V128(result))?;
64 Ok(ControlFlow::Continue(()))
65 }
66}
67define_instruction_fn! {
68 v128_or,
69 fuel_check = flat_fd(opcode::fd_extensions::V128_OR),
70 |Args { resumable, .. }| {
71 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
72 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
73 let result = array::from_fn(|i| data1[i] | data2[i]);
74 resumable.stack.push_value(Value::V128(result))?;
75 Ok(ControlFlow::Continue(()))
76 }
77}
78define_instruction_fn! {
79 v128_xor,
80 fuel_check = flat_fd(opcode::fd_extensions::V128_XOR),
81 |Args { resumable, .. }| {
82 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
83 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
84 let result = array::from_fn(|i| data1[i] ^ data2[i]);
85 resumable.stack.push_value(Value::V128(result))?;
86 Ok(ControlFlow::Continue(()))
87 }
88}
89
90define_instruction_fn! {
92 v128_bitselect,
93 fuel_check = flat_fd(opcode::fd_extensions::V128_BITSELECT),
94 |Args { resumable, .. }| {
95 let data3: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
96 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
97 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
98 let result = array::from_fn(|i| (data1[i] & data3[i]) | (data2[i] & !data3[i]));
99 resumable.stack.push_value(Value::V128(result))?;
100 Ok(ControlFlow::Continue(()))
101 }
102}
103
104define_instruction_fn! {
106 v128_any_true,
107 fuel_check = flat_fd(opcode::fd_extensions::V128_ANY_TRUE),
108 |Args { resumable, .. }| {
109 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
110 let any_true = data.into_iter().any(|byte| byte > 0);
111 resumable.stack.push_value(Value::I32(any_true as u32))?;
112 Ok(ControlFlow::Continue(()))
113 }
114}
115
116define_instruction_fn! {
118 i8x16_swizzle,
119 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SWIZZLE),
120 |Args { resumable, .. }| {
121 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
122 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
123 let result = array::from_fn(|i| *data1.get(usize::from(data2[i])).unwrap_or(&0));
124 resumable.stack.push_value(Value::V128(result))?;
125 Ok(ControlFlow::Continue(()))
126 }
127}
128
129define_instruction_fn! {
131 i8x16_shuffle,
132 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SHUFFLE),
133 |Args {
134 wasm, resumable, ..
135 }| {
136 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
137 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
138
139 let lane_selector_indices: [u8; 16] = array::from_fn(|_| wasm.read_u8().unwrap_validated());
140
141 let result = lane_selector_indices.map(|i| {
142 *data1
143 .get(usize::from(i))
144 .or_else(|| data2.get(usize::from(i) - 16))
145 .unwrap_validated()
146 });
147
148 resumable.stack.push_value(Value::V128(result))?;
149 Ok(ControlFlow::Continue(()))
150 }
151}
152
153define_instruction_fn! {
155 i8x16_splat,
156 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SPLAT),
157 |Args { resumable, .. }| {
158 let value: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
159 let lane = value as u8;
160 let data = from_lanes([lane; 16]);
161 resumable.stack.push_value(Value::V128(data))?;
162 Ok(ControlFlow::Continue(()))
163 }
164}
165define_instruction_fn! {
166 i16x8_splat,
167 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SPLAT),
168 |Args { resumable, .. }| {
169 let value: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
170 let lane = value as u16;
171 let data = from_lanes([lane; 8]);
172 resumable.stack.push_value(Value::V128(data))?;
173 Ok(ControlFlow::Continue(()))
174 }
175}
176define_instruction_fn! {
177 i32x4_splat,
178 fuel_check = flat_fd(opcode::fd_extensions::I32X4_SPLAT),
179 |Args { resumable, .. }| {
180 let lane: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
181 let data = from_lanes([lane; 4]);
182 resumable.stack.push_value(Value::V128(data))?;
183 Ok(ControlFlow::Continue(()))
184 }
185}
186define_instruction_fn! {
187 i64x2_splat,
188 fuel_check = flat_fd(opcode::fd_extensions::I64X2_SPLAT),
189 |Args { resumable, .. }| {
190 let lane: u64 = resumable.stack.pop_value().try_into().unwrap_validated();
191 let data = from_lanes([lane; 2]);
192 resumable.stack.push_value(Value::V128(data))?;
193 Ok(ControlFlow::Continue(()))
194 }
195}
196define_instruction_fn! {
197 f32x4_splat,
198 fuel_check = flat_fd(opcode::fd_extensions::F32X4_SPLAT),
199 |Args { resumable, .. }| {
200 let lane: F32 = resumable.stack.pop_value().try_into().unwrap_validated();
201 let data = from_lanes([lane; 4]);
202 resumable.stack.push_value(Value::V128(data))?;
203 Ok(ControlFlow::Continue(()))
204 }
205}
206define_instruction_fn! {
207 f64x2_splat,
208 fuel_check = flat_fd(opcode::fd_extensions::F64X2_SPLAT),
209 |Args { resumable, .. }| {
210 let lane: F64 = resumable.stack.pop_value().try_into().unwrap_validated();
211 let data = from_lanes([lane; 2]);
212 resumable.stack.push_value(Value::V128(data))?;
213 Ok(ControlFlow::Continue(()))
214 }
215}
216
217define_instruction_fn! {
219 i8x16_extract_lane_s,
220 fuel_check = flat_fd(opcode::fd_extensions::I8X16_EXTRACT_LANE_S),
221 |Args {
222 wasm, resumable, ..
223 }| {
224 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
225 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
226 let lanes: [i8; 16] = to_lanes(data);
227 let lane = *lanes.get(lane_idx).unwrap_validated();
228 resumable.stack.push_value(Value::I32(lane as u32))?;
229 Ok(ControlFlow::Continue(()))
230 }
231}
232define_instruction_fn! {
233 i8x16_extract_lane_u,
234 fuel_check = flat_fd(opcode::fd_extensions::I8X16_EXTRACT_LANE_U),
235 |Args {
236 wasm, resumable, ..
237 }| {
238 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
239 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
240 let lanes: [u8; 16] = to_lanes(data);
241 let lane = *lanes.get(lane_idx).unwrap_validated();
242 resumable.stack.push_value(Value::I32(lane as u32))?;
243 Ok(ControlFlow::Continue(()))
244 }
245}
246define_instruction_fn! {
247 i16x8_extract_lane_s,
248 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTRACT_LANE_S),
249 |Args {
250 wasm, resumable, ..
251 }| {
252 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
253 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
254 let lanes: [i16; 8] = to_lanes(data);
255 let lane = *lanes.get(lane_idx).unwrap_validated();
256 resumable.stack.push_value(Value::I32(lane as u32))?;
257 Ok(ControlFlow::Continue(()))
258 }
259}
260define_instruction_fn! {
261 i16x8_extract_lane_u,
262 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTRACT_LANE_U),
263 |Args {
264 wasm, resumable, ..
265 }| {
266 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
267 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
268 let lanes: [u16; 8] = to_lanes(data);
269 let lane = *lanes.get(lane_idx).unwrap_validated();
270 resumable.stack.push_value(Value::I32(lane as u32))?;
271 Ok(ControlFlow::Continue(()))
272 }
273}
274define_instruction_fn! {
275 i32x4_extract_lane,
276 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTRACT_LANE),
277 |Args {
278 wasm, resumable, ..
279 }| {
280 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
281 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
282 let lanes: [u32; 4] = to_lanes(data);
283 let lane = *lanes.get(lane_idx).unwrap_validated();
284 resumable.stack.push_value(Value::I32(lane))?;
285 Ok(ControlFlow::Continue(()))
286 }
287}
288define_instruction_fn! {
289 i64x2_extract_lane,
290 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTRACT_LANE),
291 |Args {
292 wasm, resumable, ..
293 }| {
294 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
295 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
296 let lanes: [u64; 2] = to_lanes(data);
297 let lane = *lanes.get(lane_idx).unwrap_validated();
298 resumable.stack.push_value(Value::I64(lane))?;
299 Ok(ControlFlow::Continue(()))
300 }
301}
302define_instruction_fn! {
303 f32x4_extract_lane,
304 fuel_check = flat_fd(opcode::fd_extensions::F32X4_EXTRACT_LANE),
305 |Args {
306 wasm, resumable, ..
307 }| {
308 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
309 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
310 let lanes: [F32; 4] = to_lanes(data);
311 let lane = *lanes.get(lane_idx).unwrap_validated();
312 resumable.stack.push_value(Value::F32(lane))?;
313 Ok(ControlFlow::Continue(()))
314 }
315}
316define_instruction_fn! {
317 f64x2_extract_lane,
318 fuel_check = flat_fd(opcode::fd_extensions::F64X2_EXTRACT_LANE),
319 |Args {
320 wasm, resumable, ..
321 }| {
322 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
323 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
324 let lanes: [F64; 2] = to_lanes(data);
325 let lane = *lanes.get(lane_idx).unwrap_validated();
326 resumable.stack.push_value(Value::F64(lane))?;
327 Ok(ControlFlow::Continue(()))
328 }
329}
330
331define_instruction_fn! {
333 i8x16_replace_lane,
334 fuel_check = flat_fd(opcode::fd_extensions::I8X16_REPLACE_LANE),
335 |Args {
336 wasm, resumable, ..
337 }| {
338 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
339 let value: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
340 let new_lane = value as u8;
341 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
342 let mut lanes: [u8; 16] = to_lanes(data);
343 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
344 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
345 Ok(ControlFlow::Continue(()))
346 }
347}
348define_instruction_fn! {
349 i16x8_replace_lane,
350 fuel_check = flat_fd(opcode::fd_extensions::I16X8_REPLACE_LANE),
351 |Args {
352 wasm, resumable, ..
353 }| {
354 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
355 let value: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
356 let new_lane = value as u16;
357 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
358 let mut lanes: [u16; 8] = to_lanes(data);
359 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
360 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
361 Ok(ControlFlow::Continue(()))
362 }
363}
364define_instruction_fn! {
365 i32x4_replace_lane,
366 fuel_check = flat_fd(opcode::fd_extensions::I32X4_REPLACE_LANE),
367 |Args {
368 wasm, resumable, ..
369 }| {
370 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
371 let new_lane: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
372 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
373 let mut lanes: [u32; 4] = to_lanes(data);
374 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
375 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
376 Ok(ControlFlow::Continue(()))
377 }
378}
379define_instruction_fn! {
380 i64x2_replace_lane,
381 fuel_check = flat_fd(opcode::fd_extensions::I64X2_REPLACE_LANE),
382 |Args {
383 wasm, resumable, ..
384 }| {
385 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
386 let new_lane: u64 = resumable.stack.pop_value().try_into().unwrap_validated();
387 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
388 let mut lanes: [u64; 2] = to_lanes(data);
389 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
390 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
391 Ok(ControlFlow::Continue(()))
392 }
393}
394define_instruction_fn! {
395 f32x4_replace_lane,
396 fuel_check = flat_fd(opcode::fd_extensions::F32X4_REPLACE_LANE),
397 |Args {
398 wasm, resumable, ..
399 }| {
400 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
401 let new_lane: F32 = resumable.stack.pop_value().try_into().unwrap_validated();
402 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
403 let mut lanes: [F32; 4] = to_lanes(data);
404 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
405 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
406 Ok(ControlFlow::Continue(()))
407 }
408}
409define_instruction_fn! {
410 f64x2_replace_lane,
411 fuel_check = flat_fd(opcode::fd_extensions::F64X2_REPLACE_LANE),
412 |Args {
413 wasm, resumable, ..
414 }| {
415 let lane_idx = usize::from(wasm.read_u8().unwrap_validated());
416 let new_lane: F64 = resumable.stack.pop_value().try_into().unwrap_validated();
417 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
418 let mut lanes: [F64; 2] = to_lanes(data);
419 *lanes.get_mut(lane_idx).unwrap_validated() = new_lane;
420 resumable.stack.push_value(Value::V128(from_lanes(lanes)))?;
421 Ok(ControlFlow::Continue(()))
422 }
423}
424
425define_instruction_fn! {
427 i8x16_abs,
428 fuel_check = flat_fd(opcode::fd_extensions::I8X16_ABS),
429 |Args { resumable, .. }| {
430 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
431 let lanes: [i8; 16] = to_lanes(data);
432 let result: [i8; 16] = lanes.map(i8::wrapping_abs);
433 resumable
434 .stack
435 .push_value(Value::V128(from_lanes(result)))?;
436 Ok(ControlFlow::Continue(()))
437 }
438}
439define_instruction_fn! {
440 i16x8_abs,
441 fuel_check = flat_fd(opcode::fd_extensions::I16X8_ABS),
442 |Args { resumable, .. }| {
443 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
444 let lanes: [i16; 8] = to_lanes(data);
445 let result: [i16; 8] = lanes.map(i16::wrapping_abs);
446 resumable
447 .stack
448 .push_value(Value::V128(from_lanes(result)))?;
449 Ok(ControlFlow::Continue(()))
450 }
451}
452define_instruction_fn! {
453 i32x4_abs,
454 fuel_check = flat_fd(opcode::fd_extensions::I32X4_ABS),
455 |Args { resumable, .. }| {
456 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
457 let lanes: [i32; 4] = to_lanes(data);
458 let result: [i32; 4] = lanes.map(i32::wrapping_abs);
459 resumable
460 .stack
461 .push_value(Value::V128(from_lanes(result)))?;
462 Ok(ControlFlow::Continue(()))
463 }
464}
465define_instruction_fn! {
466 i64x2_abs,
467 fuel_check = flat_fd(opcode::fd_extensions::I64X2_ABS),
468 |Args { resumable, .. }| {
469 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
470 let lanes: [i64; 2] = to_lanes(data);
471 let result: [i64; 2] = lanes.map(i64::wrapping_abs);
472 resumable
473 .stack
474 .push_value(Value::V128(from_lanes(result)))?;
475 Ok(ControlFlow::Continue(()))
476 }
477}
478define_instruction_fn! {
479 i8x16_neg,
480 fuel_check = flat_fd(opcode::fd_extensions::I8X16_NEG),
481 |Args { resumable, .. }| {
482 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
483 let lanes: [i8; 16] = to_lanes(data);
484 let result: [i8; 16] = lanes.map(i8::wrapping_neg);
485 resumable
486 .stack
487 .push_value(Value::V128(from_lanes(result)))?;
488 Ok(ControlFlow::Continue(()))
489 }
490}
491define_instruction_fn! {
492 i16x8_neg,
493 fuel_check = flat_fd(opcode::fd_extensions::I16X8_NEG),
494 |Args { resumable, .. }| {
495 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
496 let lanes: [i16; 8] = to_lanes(data);
497 let result: [i16; 8] = lanes.map(i16::wrapping_neg);
498 resumable
499 .stack
500 .push_value(Value::V128(from_lanes(result)))?;
501 Ok(ControlFlow::Continue(()))
502 }
503}
504define_instruction_fn! {
505 i32x4_neg,
506 fuel_check = flat_fd(opcode::fd_extensions::I32X4_NEG),
507 |Args { resumable, .. }| {
508 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
509 let lanes: [i32; 4] = to_lanes(data);
510 let result: [i32; 4] = lanes.map(i32::wrapping_neg);
511 resumable
512 .stack
513 .push_value(Value::V128(from_lanes(result)))?;
514 Ok(ControlFlow::Continue(()))
515 }
516}
517define_instruction_fn! {
518 i64x2_neg,
519 fuel_check = flat_fd(opcode::fd_extensions::I64X2_NEG),
520 |Args { resumable, .. }| {
521 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
522 let lanes: [i64; 2] = to_lanes(data);
523 let result: [i64; 2] = lanes.map(i64::wrapping_neg);
524 resumable
525 .stack
526 .push_value(Value::V128(from_lanes(result)))?;
527 Ok(ControlFlow::Continue(()))
528 }
529}
530define_instruction_fn! {
531 f32x4_abs,
532 fuel_check = flat_fd(opcode::fd_extensions::F32X4_ABS),
533 |Args { resumable, .. }| {
534 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
535 let lanes: [F32; 4] = to_lanes(data);
536 let result: [F32; 4] = lanes.map(|lane| lane.abs());
537 resumable
538 .stack
539 .push_value(Value::V128(from_lanes(result)))?;
540 Ok(ControlFlow::Continue(()))
541 }
542}
543define_instruction_fn! {
544 f64x2_abs,
545 fuel_check = flat_fd(opcode::fd_extensions::F64X2_ABS),
546 |Args { resumable, .. }| {
547 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
548 let lanes: [F64; 2] = to_lanes(data);
549 let result: [F64; 2] = lanes.map(|lane| lane.abs());
550 resumable
551 .stack
552 .push_value(Value::V128(from_lanes(result)))?;
553 Ok(ControlFlow::Continue(()))
554 }
555}
556define_instruction_fn! {
557 f32x4_neg,
558 fuel_check = flat_fd(opcode::fd_extensions::F32X4_NEG),
559 |Args { resumable, .. }| {
560 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
561 let lanes: [F32; 4] = to_lanes(data);
562 let result: [F32; 4] = lanes.map(|lane| lane.neg());
563 resumable
564 .stack
565 .push_value(Value::V128(from_lanes(result)))?;
566 Ok(ControlFlow::Continue(()))
567 }
568}
569define_instruction_fn! {
570 f64x2_neg,
571 fuel_check = flat_fd(opcode::fd_extensions::F64X2_NEG),
572 |Args { resumable, .. }| {
573 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
574 let lanes: [F64; 2] = to_lanes(data);
575 let result: [F64; 2] = lanes.map(|lane| lane.neg());
576 resumable
577 .stack
578 .push_value(Value::V128(from_lanes(result)))?;
579 Ok(ControlFlow::Continue(()))
580 }
581}
582define_instruction_fn! {
583 f32x4_sqrt,
584 fuel_check = flat_fd(opcode::fd_extensions::F32X4_SQRT),
585 |Args { resumable, .. }| {
586 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
587 let lanes: [F32; 4] = to_lanes(data);
588 let result: [F32; 4] = lanes.map(|lane| lane.sqrt());
589 resumable
590 .stack
591 .push_value(Value::V128(from_lanes(result)))?;
592 Ok(ControlFlow::Continue(()))
593 }
594}
595define_instruction_fn! {
596 f64x2_sqrt,
597 fuel_check = flat_fd(opcode::fd_extensions::F64X2_SQRT),
598 |Args { resumable, .. }| {
599 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
600 let lanes: [F64; 2] = to_lanes(data);
601 let result: [F64; 2] = lanes.map(|lane| lane.sqrt());
602 resumable
603 .stack
604 .push_value(Value::V128(from_lanes(result)))?;
605 Ok(ControlFlow::Continue(()))
606 }
607}
608define_instruction_fn! {
609 f32x4_ceil,
610 fuel_check = flat_fd(opcode::fd_extensions::F32X4_CEIL),
611 |Args { resumable, .. }| {
612 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
613 let lanes: [F32; 4] = to_lanes(data);
614 let result: [F32; 4] = lanes.map(|lane| lane.ceil());
615 resumable
616 .stack
617 .push_value(Value::V128(from_lanes(result)))?;
618 Ok(ControlFlow::Continue(()))
619 }
620}
621define_instruction_fn! {
622 f64x2_ceil,
623 fuel_check = flat_fd(opcode::fd_extensions::F64X2_CEIL),
624 |Args { resumable, .. }| {
625 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
626 let lanes: [F64; 2] = to_lanes(data);
627 let result: [F64; 2] = lanes.map(|lane| lane.ceil());
628 resumable
629 .stack
630 .push_value(Value::V128(from_lanes(result)))?;
631 Ok(ControlFlow::Continue(()))
632 }
633}
634define_instruction_fn! {
635 f32x4_floor,
636 fuel_check = flat_fd(opcode::fd_extensions::F32X4_FLOOR),
637 |Args { resumable, .. }| {
638 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
639 let lanes: [F32; 4] = to_lanes(data);
640 let result: [F32; 4] = lanes.map(|lane| lane.floor());
641 resumable
642 .stack
643 .push_value(Value::V128(from_lanes(result)))?;
644 Ok(ControlFlow::Continue(()))
645 }
646}
647define_instruction_fn! {
648 f64x2_floor,
649 fuel_check = flat_fd(opcode::fd_extensions::F64X2_FLOOR),
650 |Args { resumable, .. }| {
651 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
652 let lanes: [F64; 2] = to_lanes(data);
653 let result: [F64; 2] = lanes.map(|lane| lane.floor());
654 resumable
655 .stack
656 .push_value(Value::V128(from_lanes(result)))?;
657 Ok(ControlFlow::Continue(()))
658 }
659}
660define_instruction_fn! {
661 f32x4_trunc,
662 fuel_check = flat_fd(opcode::fd_extensions::F32X4_TRUNC),
663 |Args { resumable, .. }| {
664 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
665 let lanes: [F32; 4] = to_lanes(data);
666 let result: [F32; 4] = lanes.map(|lane| lane.trunc());
667 resumable
668 .stack
669 .push_value(Value::V128(from_lanes(result)))?;
670 Ok(ControlFlow::Continue(()))
671 }
672}
673define_instruction_fn! {
674 f64x2_trunc,
675 fuel_check = flat_fd(opcode::fd_extensions::F64X2_TRUNC),
676 |Args { resumable, .. }| {
677 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
678 let lanes: [F64; 2] = to_lanes(data);
679 let result: [F64; 2] = lanes.map(|lane| lane.trunc());
680 resumable
681 .stack
682 .push_value(Value::V128(from_lanes(result)))?;
683 Ok(ControlFlow::Continue(()))
684 }
685}
686define_instruction_fn! {
687 f32x4_nearest,
688 fuel_check = flat_fd(opcode::fd_extensions::F32X4_NEAREST),
689 |Args { resumable, .. }| {
690 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
691 let lanes: [F32; 4] = to_lanes(data);
692 let result: [F32; 4] = lanes.map(|lane| lane.nearest());
693 resumable
694 .stack
695 .push_value(Value::V128(from_lanes(result)))?;
696 Ok(ControlFlow::Continue(()))
697 }
698}
699define_instruction_fn! {
700 f64x2_nearest,
701 fuel_check = flat_fd(opcode::fd_extensions::F64X2_NEAREST),
702 |Args { resumable, .. }| {
703 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
704 let lanes: [F64; 2] = to_lanes(data);
705 let result: [F64; 2] = lanes.map(|lane| lane.nearest());
706 resumable
707 .stack
708 .push_value(Value::V128(from_lanes(result)))?;
709 Ok(ControlFlow::Continue(()))
710 }
711}
712define_instruction_fn! {
713 i8x16_popcnt,
714 fuel_check = flat_fd(opcode::fd_extensions::I8X16_POPCNT),
715 |Args { resumable, .. }| {
716 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
717 let lanes: [u8; 16] = to_lanes(data);
718 let result: [u8; 16] = lanes.map(|lane| lane.count_ones() as u8);
719 resumable
720 .stack
721 .push_value(Value::V128(from_lanes(result)))?;
722 Ok(ControlFlow::Continue(()))
723 }
724}
725
726define_instruction_fn! {
728 i8x16_add,
729 fuel_check = flat_fd(opcode::fd_extensions::I8X16_ADD),
730 |Args { resumable, .. }| {
731 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
732 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
733 let lanes2: [u8; 16] = to_lanes(data2);
734 let lanes1: [u8; 16] = to_lanes(data1);
735 let result: [u8; 16] = array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
736 resumable
737 .stack
738 .push_value(Value::V128(from_lanes(result)))?;
739 Ok(ControlFlow::Continue(()))
740 }
741}
742define_instruction_fn! {
743 i16x8_add,
744 fuel_check = flat_fd(opcode::fd_extensions::I16X8_ADD),
745 |Args { resumable, .. }| {
746 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
747 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
748 let lanes2: [u16; 8] = to_lanes(data2);
749 let lanes1: [u16; 8] = to_lanes(data1);
750 let result: [u16; 8] = array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
751 resumable
752 .stack
753 .push_value(Value::V128(from_lanes(result)))?;
754 Ok(ControlFlow::Continue(()))
755 }
756}
757define_instruction_fn! {
758 i32x4_add,
759 fuel_check = flat_fd(opcode::fd_extensions::I32X4_ADD),
760 |Args { resumable, .. }| {
761 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
762 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
763 let lanes2: [u32; 4] = to_lanes(data2);
764 let lanes1: [u32; 4] = to_lanes(data1);
765 let result: [u32; 4] = array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
766 resumable
767 .stack
768 .push_value(Value::V128(from_lanes(result)))?;
769 Ok(ControlFlow::Continue(()))
770 }
771}
772define_instruction_fn! {
773 i64x2_add,
774 fuel_check = flat_fd(opcode::fd_extensions::I64X2_ADD),
775 |Args { resumable, .. }| {
776 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
777 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
778 let lanes2: [u64; 2] = to_lanes(data2);
779 let lanes1: [u64; 2] = to_lanes(data1);
780 let result: [u64; 2] = array::from_fn(|i| lanes1[i].wrapping_add(lanes2[i]));
781 resumable
782 .stack
783 .push_value(Value::V128(from_lanes(result)))?;
784 Ok(ControlFlow::Continue(()))
785 }
786}
787define_instruction_fn! {
788 i8x16_sub,
789 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SUB),
790 |Args { resumable, .. }| {
791 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
792 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
793 let lanes2: [u8; 16] = to_lanes(data2);
794 let lanes1: [u8; 16] = to_lanes(data1);
795 let result: [u8; 16] = array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
796 resumable
797 .stack
798 .push_value(Value::V128(from_lanes(result)))?;
799 Ok(ControlFlow::Continue(()))
800 }
801}
802define_instruction_fn! {
803 i16x8_sub,
804 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SUB),
805 |Args { resumable, .. }| {
806 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
807 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
808 let lanes2: [u16; 8] = to_lanes(data2);
809 let lanes1: [u16; 8] = to_lanes(data1);
810 let result: [u16; 8] = array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
811 resumable
812 .stack
813 .push_value(Value::V128(from_lanes(result)))?;
814 Ok(ControlFlow::Continue(()))
815 }
816}
817define_instruction_fn! {
818 i32x4_sub,
819 fuel_check = flat_fd(opcode::fd_extensions::I32X4_SUB),
820 |Args { resumable, .. }| {
821 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
822 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
823 let lanes2: [u32; 4] = to_lanes(data2);
824 let lanes1: [u32; 4] = to_lanes(data1);
825 let result: [u32; 4] = array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
826 resumable
827 .stack
828 .push_value(Value::V128(from_lanes(result)))?;
829 Ok(ControlFlow::Continue(()))
830 }
831}
832define_instruction_fn! {
833 i64x2_sub,
834 fuel_check = flat_fd(opcode::fd_extensions::I64X2_SUB),
835 |Args { resumable, .. }| {
836 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
837 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
838 let lanes2: [u64; 2] = to_lanes(data2);
839 let lanes1: [u64; 2] = to_lanes(data1);
840 let result: [u64; 2] = array::from_fn(|i| lanes1[i].wrapping_sub(lanes2[i]));
841 resumable
842 .stack
843 .push_value(Value::V128(from_lanes(result)))?;
844 Ok(ControlFlow::Continue(()))
845 }
846}
847define_instruction_fn! {
848 f32x4_add,
849 fuel_check = flat_fd(opcode::fd_extensions::F32X4_ADD),
850 |Args { resumable, .. }| {
851 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
852 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
853 let lanes2: [F32; 4] = to_lanes(data2);
854 let lanes1: [F32; 4] = to_lanes(data1);
855 let result: [F32; 4] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
856 resumable
857 .stack
858 .push_value(Value::V128(from_lanes(result)))?;
859 Ok(ControlFlow::Continue(()))
860 }
861}
862define_instruction_fn! {
863 f64x2_add,
864 fuel_check = flat_fd(opcode::fd_extensions::F64X2_ADD),
865 |Args { resumable, .. }| {
866 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
867 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
868 let lanes2: [F64; 2] = to_lanes(data2);
869 let lanes1: [F64; 2] = to_lanes(data1);
870 let result: [F64; 2] = array::from_fn(|i| lanes1[i].add(lanes2[i]));
871 resumable
872 .stack
873 .push_value(Value::V128(from_lanes(result)))?;
874 Ok(ControlFlow::Continue(()))
875 }
876}
877define_instruction_fn! {
878 f32x4_sub,
879 fuel_check = flat_fd(opcode::fd_extensions::F32X4_SUB),
880 |Args { resumable, .. }| {
881 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
882 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
883 let lanes2: [F32; 4] = to_lanes(data2);
884 let lanes1: [F32; 4] = to_lanes(data1);
885 let result: [F32; 4] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
886 resumable
887 .stack
888 .push_value(Value::V128(from_lanes(result)))?;
889 Ok(ControlFlow::Continue(()))
890 }
891}
892define_instruction_fn! {
893 f64x2_sub,
894 fuel_check = flat_fd(opcode::fd_extensions::F64X2_SUB),
895 |Args { resumable, .. }| {
896 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
897 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
898 let lanes2: [F64; 2] = to_lanes(data2);
899 let lanes1: [F64; 2] = to_lanes(data1);
900 let result: [F64; 2] = array::from_fn(|i| lanes1[i].sub(lanes2[i]));
901 resumable
902 .stack
903 .push_value(Value::V128(from_lanes(result)))?;
904 Ok(ControlFlow::Continue(()))
905 }
906}
907define_instruction_fn! {
908 f32x4_mul,
909 fuel_check = flat_fd(opcode::fd_extensions::F32X4_MUL),
910 |Args { resumable, .. }| {
911 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
912 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
913 let lanes2: [F32; 4] = to_lanes(data2);
914 let lanes1: [F32; 4] = to_lanes(data1);
915 let result: [F32; 4] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
916 resumable
917 .stack
918 .push_value(Value::V128(from_lanes(result)))?;
919 Ok(ControlFlow::Continue(()))
920 }
921}
922define_instruction_fn! {
923 f64x2_mul,
924 fuel_check = flat_fd(opcode::fd_extensions::F64X2_MUL),
925 |Args { resumable, .. }| {
926 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
927 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
928 let lanes2: [F64; 2] = to_lanes(data2);
929 let lanes1: [F64; 2] = to_lanes(data1);
930 let result: [F64; 2] = array::from_fn(|i| lanes1[i].mul(lanes2[i]));
931 resumable
932 .stack
933 .push_value(Value::V128(from_lanes(result)))?;
934 Ok(ControlFlow::Continue(()))
935 }
936}
937define_instruction_fn! {
938 f32x4_div,
939 fuel_check = flat_fd(opcode::fd_extensions::F32X4_DIV),
940 |Args { resumable, .. }| {
941 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
942 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
943 let lanes2: [F32; 4] = to_lanes(data2);
944 let lanes1: [F32; 4] = to_lanes(data1);
945 let result: [F32; 4] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
946 resumable
947 .stack
948 .push_value(Value::V128(from_lanes(result)))?;
949 Ok(ControlFlow::Continue(()))
950 }
951}
952define_instruction_fn! {
953 f64x2_div,
954 fuel_check = flat_fd(opcode::fd_extensions::F64X2_DIV),
955 |Args { resumable, .. }| {
956 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
957 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
958 let lanes2: [F64; 2] = to_lanes(data2);
959 let lanes1: [F64; 2] = to_lanes(data1);
960 let result: [F64; 2] = array::from_fn(|i| lanes1[i].div(lanes2[i]));
961 resumable
962 .stack
963 .push_value(Value::V128(from_lanes(result)))?;
964 Ok(ControlFlow::Continue(()))
965 }
966}
967define_instruction_fn! {
968 f32x4_min,
969 fuel_check = flat_fd(opcode::fd_extensions::F32X4_MIN),
970 |Args { resumable, .. }| {
971 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
972 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
973 let lanes2: [F32; 4] = to_lanes(data2);
974 let lanes1: [F32; 4] = to_lanes(data1);
975 let result: [F32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
976 resumable
977 .stack
978 .push_value(Value::V128(from_lanes(result)))?;
979 Ok(ControlFlow::Continue(()))
980 }
981}
982define_instruction_fn! {
983 f64x2_min,
984 fuel_check = flat_fd(opcode::fd_extensions::F64X2_MIN),
985 |Args { resumable, .. }| {
986 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
987 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
988 let lanes2: [F64; 2] = to_lanes(data2);
989 let lanes1: [F64; 2] = to_lanes(data1);
990 let result: [F64; 2] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
991 resumable
992 .stack
993 .push_value(Value::V128(from_lanes(result)))?;
994 Ok(ControlFlow::Continue(()))
995 }
996}
997define_instruction_fn! {
998 f32x4_max,
999 fuel_check = flat_fd(opcode::fd_extensions::F32X4_MAX),
1000 |Args { resumable, .. }| {
1001 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1002 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1003 let lanes2: [F32; 4] = to_lanes(data2);
1004 let lanes1: [F32; 4] = to_lanes(data1);
1005 let result: [F32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1006 resumable
1007 .stack
1008 .push_value(Value::V128(from_lanes(result)))?;
1009 Ok(ControlFlow::Continue(()))
1010 }
1011}
1012define_instruction_fn! {
1013 f64x2_max,
1014 fuel_check = flat_fd(opcode::fd_extensions::F64X2_MAX),
1015 |Args { resumable, .. }| {
1016 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1017 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1018 let lanes2: [F64; 2] = to_lanes(data2);
1019 let lanes1: [F64; 2] = to_lanes(data1);
1020 let result: [F64; 2] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1021 resumable
1022 .stack
1023 .push_value(Value::V128(from_lanes(result)))?;
1024 Ok(ControlFlow::Continue(()))
1025 }
1026}
1027define_instruction_fn! {
1028 f32x4_pmin,
1029 fuel_check = flat_fd(opcode::fd_extensions::F32X4_PMIN),
1030 |Args { resumable, .. }| {
1031 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1032 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1033 let lanes2: [F32; 4] = to_lanes(data2);
1034 let lanes1: [F32; 4] = to_lanes(data1);
1035 let result: [F32; 4] = array::from_fn(|i| {
1036 let v1 = lanes1[i];
1037 let v2 = lanes2[i];
1038 if v2 < v1 {
1039 v2
1040 } else {
1041 v1
1042 }
1043 });
1044 resumable
1045 .stack
1046 .push_value(Value::V128(from_lanes(result)))?;
1047 Ok(ControlFlow::Continue(()))
1048 }
1049}
1050define_instruction_fn! {
1051 f64x2_pmin,
1052 fuel_check = flat_fd(opcode::fd_extensions::F64X2_PMIN),
1053 |Args { resumable, .. }| {
1054 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1055 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1056 let lanes2: [F64; 2] = to_lanes(data2);
1057 let lanes1: [F64; 2] = to_lanes(data1);
1058 let result: [F64; 2] = array::from_fn(|i| {
1059 let v1 = lanes1[i];
1060 let v2 = lanes2[i];
1061 if v2 < v1 {
1062 v2
1063 } else {
1064 v1
1065 }
1066 });
1067 resumable
1068 .stack
1069 .push_value(Value::V128(from_lanes(result)))?;
1070 Ok(ControlFlow::Continue(()))
1071 }
1072}
1073define_instruction_fn! {
1074 f32x4_pmax,
1075 fuel_check = flat_fd(opcode::fd_extensions::F32X4_PMAX),
1076 |Args { resumable, .. }| {
1077 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1078 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1079 let lanes2: [F32; 4] = to_lanes(data2);
1080 let lanes1: [F32; 4] = to_lanes(data1);
1081 let result: [F32; 4] = array::from_fn(|i| {
1082 let v1 = lanes1[i];
1083 let v2 = lanes2[i];
1084 if v1 < v2 {
1085 v2
1086 } else {
1087 v1
1088 }
1089 });
1090 resumable
1091 .stack
1092 .push_value(Value::V128(from_lanes(result)))?;
1093 Ok(ControlFlow::Continue(()))
1094 }
1095}
1096define_instruction_fn! {
1097 f64x2_pmax,
1098 fuel_check = flat_fd(opcode::fd_extensions::F64X2_PMAX),
1099 |Args { resumable, .. }| {
1100 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1101 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1102 let lanes2: [F64; 2] = to_lanes(data2);
1103 let lanes1: [F64; 2] = to_lanes(data1);
1104 let result: [F64; 2] = array::from_fn(|i| {
1105 let v1 = lanes1[i];
1106 let v2 = lanes2[i];
1107 if v1 < v2 {
1108 v2
1109 } else {
1110 v1
1111 }
1112 });
1113 resumable
1114 .stack
1115 .push_value(Value::V128(from_lanes(result)))?;
1116 Ok(ControlFlow::Continue(()))
1117 }
1118}
1119define_instruction_fn! {
1120 i8x16_min_s,
1121 fuel_check = flat_fd(opcode::fd_extensions::I8X16_MIN_S),
1122 |Args { resumable, .. }| {
1123 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1124 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1125 let lanes2: [i8; 16] = to_lanes(data2);
1126 let lanes1: [i8; 16] = to_lanes(data1);
1127 let result: [i8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1128 resumable
1129 .stack
1130 .push_value(Value::V128(from_lanes(result)))?;
1131 Ok(ControlFlow::Continue(()))
1132 }
1133}
1134define_instruction_fn! {
1135 i16x8_min_s,
1136 fuel_check = flat_fd(opcode::fd_extensions::I16X8_MIN_S),
1137 |Args { resumable, .. }| {
1138 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1139 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1140 let lanes2: [i16; 8] = to_lanes(data2);
1141 let lanes1: [i16; 8] = to_lanes(data1);
1142 let result: [i16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1143 resumable
1144 .stack
1145 .push_value(Value::V128(from_lanes(result)))?;
1146 Ok(ControlFlow::Continue(()))
1147 }
1148}
1149define_instruction_fn! {
1150 i32x4_min_s,
1151 fuel_check = flat_fd(opcode::fd_extensions::I32X4_MIN_S),
1152 |Args { resumable, .. }| {
1153 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1154 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1155 let lanes2: [i32; 4] = to_lanes(data2);
1156 let lanes1: [i32; 4] = to_lanes(data1);
1157 let result: [i32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1158 resumable
1159 .stack
1160 .push_value(Value::V128(from_lanes(result)))?;
1161 Ok(ControlFlow::Continue(()))
1162 }
1163}
1164define_instruction_fn! {
1165 i8x16_min_u,
1166 fuel_check = flat_fd(opcode::fd_extensions::I8X16_MIN_U),
1167 |Args { resumable, .. }| {
1168 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1169 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1170 let lanes2: [u8; 16] = to_lanes(data2);
1171 let lanes1: [u8; 16] = to_lanes(data1);
1172 let result: [u8; 16] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1173 resumable
1174 .stack
1175 .push_value(Value::V128(from_lanes(result)))?;
1176 Ok(ControlFlow::Continue(()))
1177 }
1178}
1179define_instruction_fn! {
1180 i16x8_min_u,
1181 fuel_check = flat_fd(opcode::fd_extensions::I16X8_MIN_U),
1182 |Args { resumable, .. }| {
1183 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1184 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1185 let lanes2: [u16; 8] = to_lanes(data2);
1186 let lanes1: [u16; 8] = to_lanes(data1);
1187 let result: [u16; 8] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1188 resumable
1189 .stack
1190 .push_value(Value::V128(from_lanes(result)))?;
1191 Ok(ControlFlow::Continue(()))
1192 }
1193}
1194define_instruction_fn! {
1195 i32x4_min_u,
1196 fuel_check = flat_fd(opcode::fd_extensions::I32X4_MIN_U),
1197 |Args { resumable, .. }| {
1198 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1199 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1200 let lanes2: [u32; 4] = to_lanes(data2);
1201 let lanes1: [u32; 4] = to_lanes(data1);
1202 let result: [u32; 4] = array::from_fn(|i| lanes1[i].min(lanes2[i]));
1203 resumable
1204 .stack
1205 .push_value(Value::V128(from_lanes(result)))?;
1206 Ok(ControlFlow::Continue(()))
1207 }
1208}
1209define_instruction_fn! {
1210 i8x16_max_s,
1211 fuel_check = flat_fd(opcode::fd_extensions::I8X16_MAX_S),
1212 |Args { resumable, .. }| {
1213 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1214 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1215 let lanes2: [i8; 16] = to_lanes(data2);
1216 let lanes1: [i8; 16] = to_lanes(data1);
1217 let result: [i8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1218 resumable
1219 .stack
1220 .push_value(Value::V128(from_lanes(result)))?;
1221 Ok(ControlFlow::Continue(()))
1222 }
1223}
1224define_instruction_fn! {
1225 i16x8_max_s,
1226 fuel_check = flat_fd(opcode::fd_extensions::I16X8_MAX_S),
1227 |Args { resumable, .. }| {
1228 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1229 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1230 let lanes2: [i16; 8] = to_lanes(data2);
1231 let lanes1: [i16; 8] = to_lanes(data1);
1232 let result: [i16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1233 resumable
1234 .stack
1235 .push_value(Value::V128(from_lanes(result)))?;
1236 Ok(ControlFlow::Continue(()))
1237 }
1238}
1239define_instruction_fn! {
1240 i32x4_max_s,
1241 fuel_check = flat_fd(opcode::fd_extensions::I32X4_MAX_S),
1242 |Args { resumable, .. }| {
1243 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1244 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1245 let lanes2: [i32; 4] = to_lanes(data2);
1246 let lanes1: [i32; 4] = to_lanes(data1);
1247 let result: [i32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1248 resumable
1249 .stack
1250 .push_value(Value::V128(from_lanes(result)))?;
1251 Ok(ControlFlow::Continue(()))
1252 }
1253}
1254define_instruction_fn! {
1255 i8x16_max_u,
1256 fuel_check = flat_fd(opcode::fd_extensions::I8X16_MAX_U),
1257 |Args { resumable, .. }| {
1258 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1259 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1260 let lanes2: [u8; 16] = to_lanes(data2);
1261 let lanes1: [u8; 16] = to_lanes(data1);
1262 let result: [u8; 16] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1263 resumable
1264 .stack
1265 .push_value(Value::V128(from_lanes(result)))?;
1266 Ok(ControlFlow::Continue(()))
1267 }
1268}
1269define_instruction_fn! {
1270 i16x8_max_u,
1271 fuel_check = flat_fd(opcode::fd_extensions::I16X8_MAX_U),
1272 |Args { resumable, .. }| {
1273 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1274 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1275 let lanes2: [u16; 8] = to_lanes(data2);
1276 let lanes1: [u16; 8] = to_lanes(data1);
1277 let result: [u16; 8] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1278 resumable
1279 .stack
1280 .push_value(Value::V128(from_lanes(result)))?;
1281 Ok(ControlFlow::Continue(()))
1282 }
1283}
1284define_instruction_fn! {
1285 i32x4_max_u,
1286 fuel_check = flat_fd(opcode::fd_extensions::I32X4_MAX_U),
1287 |Args { resumable, .. }| {
1288 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1289 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1290 let lanes2: [u32; 4] = to_lanes(data2);
1291 let lanes1: [u32; 4] = to_lanes(data1);
1292 let result: [u32; 4] = array::from_fn(|i| lanes1[i].max(lanes2[i]));
1293 resumable
1294 .stack
1295 .push_value(Value::V128(from_lanes(result)))?;
1296 Ok(ControlFlow::Continue(()))
1297 }
1298}
1299
1300define_instruction_fn! {
1301 i8x16_add_sat_s,
1302 fuel_check = flat_fd(opcode::fd_extensions::I8X16_ADD_SAT_S),
1303 |Args { resumable, .. }| {
1304 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1305 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1306 let lanes2: [i8; 16] = to_lanes(data2);
1307 let lanes1: [i8; 16] = to_lanes(data1);
1308 let result: [i8; 16] = array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
1309 resumable
1310 .stack
1311 .push_value(Value::V128(from_lanes(result)))?;
1312 Ok(ControlFlow::Continue(()))
1313 }
1314}
1315define_instruction_fn! {
1316 i16x8_add_sat_s,
1317 fuel_check = flat_fd(opcode::fd_extensions::I16X8_ADD_SAT_S),
1318 |Args { resumable, .. }| {
1319 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1320 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1321 let lanes2: [i16; 8] = to_lanes(data2);
1322 let lanes1: [i16; 8] = to_lanes(data1);
1323 let result: [i16; 8] = array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
1324 resumable
1325 .stack
1326 .push_value(Value::V128(from_lanes(result)))?;
1327 Ok(ControlFlow::Continue(()))
1328 }
1329}
1330define_instruction_fn! {
1331 i8x16_add_sat_u,
1332 fuel_check = flat_fd(opcode::fd_extensions::I8X16_ADD_SAT_U),
1333 |Args { resumable, .. }| {
1334 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1335 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1336 let lanes2: [u8; 16] = to_lanes(data2);
1337 let lanes1: [u8; 16] = to_lanes(data1);
1338 let result: [u8; 16] = array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
1339 resumable
1340 .stack
1341 .push_value(Value::V128(from_lanes(result)))?;
1342 Ok(ControlFlow::Continue(()))
1343 }
1344}
1345define_instruction_fn! {
1346 i16x8_add_sat_u,
1347 fuel_check = flat_fd(opcode::fd_extensions::I16X8_ADD_SAT_U),
1348 |Args { resumable, .. }| {
1349 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1350 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1351 let lanes2: [u16; 8] = to_lanes(data2);
1352 let lanes1: [u16; 8] = to_lanes(data1);
1353 let result: [u16; 8] = array::from_fn(|i| lanes1[i].saturating_add(lanes2[i]));
1354 resumable
1355 .stack
1356 .push_value(Value::V128(from_lanes(result)))?;
1357 Ok(ControlFlow::Continue(()))
1358 }
1359}
1360define_instruction_fn! {
1361 i8x16_sub_sat_s,
1362 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SUB_SAT_S),
1363 |Args { resumable, .. }| {
1364 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1365 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1366 let lanes2: [i8; 16] = to_lanes(data2);
1367 let lanes1: [i8; 16] = to_lanes(data1);
1368 let result: [i8; 16] = array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
1369 resumable
1370 .stack
1371 .push_value(Value::V128(from_lanes(result)))?;
1372 Ok(ControlFlow::Continue(()))
1373 }
1374}
1375define_instruction_fn! {
1376 i16x8_sub_sat_s,
1377 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SUB_SAT_S),
1378 |Args { resumable, .. }| {
1379 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1380 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1381 let lanes2: [i16; 8] = to_lanes(data2);
1382 let lanes1: [i16; 8] = to_lanes(data1);
1383 let result: [i16; 8] = array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
1384 resumable
1385 .stack
1386 .push_value(Value::V128(from_lanes(result)))?;
1387 Ok(ControlFlow::Continue(()))
1388 }
1389}
1390define_instruction_fn! {
1391 i8x16_sub_sat_u,
1392 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SUB_SAT_U),
1393 |Args { resumable, .. }| {
1394 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1395 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1396 let lanes2: [u8; 16] = to_lanes(data2);
1397 let lanes1: [u8; 16] = to_lanes(data1);
1398 let result: [u8; 16] = array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
1399 resumable
1400 .stack
1401 .push_value(Value::V128(from_lanes(result)))?;
1402 Ok(ControlFlow::Continue(()))
1403 }
1404}
1405define_instruction_fn! {
1406 i16x8_sub_sat_u,
1407 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SUB_SAT_U),
1408 |Args { resumable, .. }| {
1409 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1410 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1411 let lanes2: [u16; 8] = to_lanes(data2);
1412 let lanes1: [u16; 8] = to_lanes(data1);
1413 let result: [u16; 8] = array::from_fn(|i| lanes1[i].saturating_sub(lanes2[i]));
1414 resumable
1415 .stack
1416 .push_value(Value::V128(from_lanes(result)))?;
1417 Ok(ControlFlow::Continue(()))
1418 }
1419}
1420define_instruction_fn! {
1421 i16x8_mul,
1422 fuel_check = flat_fd(opcode::fd_extensions::I16X8_MUL),
1423 |Args { resumable, .. }| {
1424 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1425 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1426 let lanes2: [u16; 8] = to_lanes(data2);
1427 let lanes1: [u16; 8] = to_lanes(data1);
1428 let result: [u16; 8] = array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
1429 resumable
1430 .stack
1431 .push_value(Value::V128(from_lanes(result)))?;
1432 Ok(ControlFlow::Continue(()))
1433 }
1434}
1435define_instruction_fn! {
1436 i32x4_mul,
1437 fuel_check = flat_fd(opcode::fd_extensions::I32X4_MUL),
1438 |Args { resumable, .. }| {
1439 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1440 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1441 let lanes2: [u32; 4] = to_lanes(data2);
1442 let lanes1: [u32; 4] = to_lanes(data1);
1443 let result: [u32; 4] = array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
1444 resumable
1445 .stack
1446 .push_value(Value::V128(from_lanes(result)))?;
1447 Ok(ControlFlow::Continue(()))
1448 }
1449}
1450define_instruction_fn! {
1451 i64x2_mul,
1452 fuel_check = flat_fd(opcode::fd_extensions::I64X2_MUL),
1453 |Args { resumable, .. }| {
1454 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1455 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1456 let lanes2: [u64; 2] = to_lanes(data2);
1457 let lanes1: [u64; 2] = to_lanes(data1);
1458 let result: [u64; 2] = array::from_fn(|i| lanes1[i].wrapping_mul(lanes2[i]));
1459 resumable
1460 .stack
1461 .push_value(Value::V128(from_lanes(result)))?;
1462 Ok(ControlFlow::Continue(()))
1463 }
1464}
1465define_instruction_fn! {
1466 i8x16_avgr_u,
1467 fuel_check = flat_fd(opcode::fd_extensions::I8X16_AVGR_U),
1468 |Args { resumable, .. }| {
1469 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1470 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1471 let lanes2: [u8; 16] = to_lanes(data2);
1472 let lanes1: [u8; 16] = to_lanes(data1);
1473 let result: [u8; 16] =
1474 array::from_fn(|i| (lanes1[i] as u16 + lanes2[i] as u16).div_ceil(2) as u8);
1475 resumable
1476 .stack
1477 .push_value(Value::V128(from_lanes(result)))?;
1478 Ok(ControlFlow::Continue(()))
1479 }
1480}
1481define_instruction_fn! {
1482 i16x8_avgr_u,
1483 fuel_check = flat_fd(opcode::fd_extensions::I16X8_AVGR_U),
1484 |Args { resumable, .. }| {
1485 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1486 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1487 let lanes2: [u16; 8] = to_lanes(data2);
1488 let lanes1: [u16; 8] = to_lanes(data1);
1489 let result: [u16; 8] =
1490 array::from_fn(|i| (lanes1[i] as u32 + lanes2[i] as u32).div_ceil(2) as u16);
1491 resumable
1492 .stack
1493 .push_value(Value::V128(from_lanes(result)))?;
1494 Ok(ControlFlow::Continue(()))
1495 }
1496}
1497define_instruction_fn! {
1498 i16x8_q15mulrsat_s,
1499 fuel_check = flat_fd(opcode::fd_extensions::I16X8_Q15MULRSAT_S),
1500 |Args { resumable, .. }| {
1501 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1502 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1503 let lanes2: [i16; 8] = to_lanes(data2);
1504 let lanes1: [i16; 8] = to_lanes(data1);
1505 let result: [i16; 8] = array::from_fn(|i| {
1506 (((lanes1[i] as i64).mul(lanes2[i] as i64) + 2i64.pow(14)) >> 15i64)
1507 .clamp(i16::MIN as i64, i16::MAX as i64) as i16
1508 });
1509 resumable
1510 .stack
1511 .push_value(Value::V128(from_lanes(result)))?;
1512 Ok(ControlFlow::Continue(()))
1513 }
1514}
1515
1516define_instruction_fn! {
1518 i8x16_eq,
1519 fuel_check = flat_fd(opcode::fd_extensions::I8X16_EQ),
1520 |Args { resumable, .. }| {
1521 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1522 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1523 let lanes2: [u8; 16] = to_lanes(data2);
1524 let lanes1: [u8; 16] = to_lanes(data1);
1525 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i8).neg());
1526 resumable
1527 .stack
1528 .push_value(Value::V128(from_lanes(result)))?;
1529 Ok(ControlFlow::Continue(()))
1530 }
1531}
1532define_instruction_fn! {
1533 i16x8_eq,
1534 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EQ),
1535 |Args { resumable, .. }| {
1536 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1537 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1538 let lanes2: [u16; 8] = to_lanes(data2);
1539 let lanes1: [u16; 8] = to_lanes(data1);
1540 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i16).neg());
1541 resumable
1542 .stack
1543 .push_value(Value::V128(from_lanes(result)))?;
1544 Ok(ControlFlow::Continue(()))
1545 }
1546}
1547define_instruction_fn! {
1548 i32x4_eq,
1549 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EQ),
1550 |Args { resumable, .. }| {
1551 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1552 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1553 let lanes2: [u32; 4] = to_lanes(data2);
1554 let lanes1: [u32; 4] = to_lanes(data1);
1555 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
1556 resumable
1557 .stack
1558 .push_value(Value::V128(from_lanes(result)))?;
1559 Ok(ControlFlow::Continue(()))
1560 }
1561}
1562define_instruction_fn! {
1563 i64x2_eq,
1564 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EQ),
1565 |Args { resumable, .. }| {
1566 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1567 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1568 let lanes2: [u64; 2] = to_lanes(data2);
1569 let lanes1: [u64; 2] = to_lanes(data1);
1570 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
1571 resumable
1572 .stack
1573 .push_value(Value::V128(from_lanes(result)))?;
1574 Ok(ControlFlow::Continue(()))
1575 }
1576}
1577define_instruction_fn! {
1578 i8x16_ne,
1579 fuel_check = flat_fd(opcode::fd_extensions::I8X16_NE),
1580 |Args { resumable, .. }| {
1581 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1582 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1583 let lanes2: [u8; 16] = to_lanes(data2);
1584 let lanes1: [u8; 16] = to_lanes(data1);
1585 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i8).neg());
1586 resumable
1587 .stack
1588 .push_value(Value::V128(from_lanes(result)))?;
1589 Ok(ControlFlow::Continue(()))
1590 }
1591}
1592define_instruction_fn! {
1593 i16x8_ne,
1594 fuel_check = flat_fd(opcode::fd_extensions::I16X8_NE),
1595 |Args { resumable, .. }| {
1596 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1597 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1598 let lanes2: [u16; 8] = to_lanes(data2);
1599 let lanes1: [u16; 8] = to_lanes(data1);
1600 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i16).neg());
1601 resumable
1602 .stack
1603 .push_value(Value::V128(from_lanes(result)))?;
1604 Ok(ControlFlow::Continue(()))
1605 }
1606}
1607define_instruction_fn! {
1608 i32x4_ne,
1609 fuel_check = flat_fd(opcode::fd_extensions::I32X4_NE),
1610 |Args { resumable, .. }| {
1611 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1612 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1613 let lanes2: [u32; 4] = to_lanes(data2);
1614 let lanes1: [u32; 4] = to_lanes(data1);
1615 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
1616 resumable
1617 .stack
1618 .push_value(Value::V128(from_lanes(result)))?;
1619 Ok(ControlFlow::Continue(()))
1620 }
1621}
1622define_instruction_fn! {
1623 i64x2_ne,
1624 fuel_check = flat_fd(opcode::fd_extensions::I64X2_NE),
1625 |Args { resumable, .. }| {
1626 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1627 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1628 let lanes2: [u64; 2] = to_lanes(data2);
1629 let lanes1: [u64; 2] = to_lanes(data1);
1630 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
1631 resumable
1632 .stack
1633 .push_value(Value::V128(from_lanes(result)))?;
1634 Ok(ControlFlow::Continue(()))
1635 }
1636}
1637define_instruction_fn! {
1638 i8x16_lt_s,
1639 fuel_check = flat_fd(opcode::fd_extensions::I8X16_LT_S),
1640 |Args { resumable, .. }| {
1641 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1642 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1643 let lanes2: [i8; 16] = to_lanes(data2);
1644 let lanes1: [i8; 16] = to_lanes(data1);
1645 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
1646 resumable
1647 .stack
1648 .push_value(Value::V128(from_lanes(result)))?;
1649 Ok(ControlFlow::Continue(()))
1650 }
1651}
1652define_instruction_fn! {
1653 i16x8_lt_s,
1654 fuel_check = flat_fd(opcode::fd_extensions::I16X8_LT_S),
1655 |Args { resumable, .. }| {
1656 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1657 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1658 let lanes2: [i16; 8] = to_lanes(data2);
1659 let lanes1: [i16; 8] = to_lanes(data1);
1660 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
1661 resumable
1662 .stack
1663 .push_value(Value::V128(from_lanes(result)))?;
1664 Ok(ControlFlow::Continue(()))
1665 }
1666}
1667define_instruction_fn! {
1668 i32x4_lt_s,
1669 fuel_check = flat_fd(opcode::fd_extensions::I32X4_LT_S),
1670 |Args { resumable, .. }| {
1671 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1672 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1673 let lanes2: [i32; 4] = to_lanes(data2);
1674 let lanes1: [i32; 4] = to_lanes(data1);
1675 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
1676 resumable
1677 .stack
1678 .push_value(Value::V128(from_lanes(result)))?;
1679 Ok(ControlFlow::Continue(()))
1680 }
1681}
1682define_instruction_fn! {
1683 i64x2_lt_s,
1684 fuel_check = flat_fd(opcode::fd_extensions::I64X2_LT_S),
1685 |Args { resumable, .. }| {
1686 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1687 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1688 let lanes2: [i64; 2] = to_lanes(data2);
1689 let lanes1: [i64; 2] = to_lanes(data1);
1690 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
1691 resumable
1692 .stack
1693 .push_value(Value::V128(from_lanes(result)))?;
1694 Ok(ControlFlow::Continue(()))
1695 }
1696}
1697define_instruction_fn! {
1698 i8x16_lt_u,
1699 fuel_check = flat_fd(opcode::fd_extensions::I8X16_LT_U),
1700 |Args { resumable, .. }| {
1701 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1702 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1703 let lanes2: [u8; 16] = to_lanes(data2);
1704 let lanes1: [u8; 16] = to_lanes(data1);
1705 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i8).neg());
1706 resumable
1707 .stack
1708 .push_value(Value::V128(from_lanes(result)))?;
1709 Ok(ControlFlow::Continue(()))
1710 }
1711}
1712define_instruction_fn! {
1713 i16x8_lt_u,
1714 fuel_check = flat_fd(opcode::fd_extensions::I16X8_LT_U),
1715 |Args { resumable, .. }| {
1716 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1717 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1718 let lanes2: [u16; 8] = to_lanes(data2);
1719 let lanes1: [u16; 8] = to_lanes(data1);
1720 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i16).neg());
1721 resumable
1722 .stack
1723 .push_value(Value::V128(from_lanes(result)))?;
1724 Ok(ControlFlow::Continue(()))
1725 }
1726}
1727define_instruction_fn! {
1728 i32x4_lt_u,
1729 fuel_check = flat_fd(opcode::fd_extensions::I32X4_LT_U),
1730 |Args { resumable, .. }| {
1731 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1732 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1733 let lanes2: [u32; 4] = to_lanes(data2);
1734 let lanes1: [u32; 4] = to_lanes(data1);
1735 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
1736 resumable
1737 .stack
1738 .push_value(Value::V128(from_lanes(result)))?;
1739 Ok(ControlFlow::Continue(()))
1740 }
1741}
1742define_instruction_fn! {
1743 i8x16_gt_s,
1744 fuel_check = flat_fd(opcode::fd_extensions::I8X16_GT_S),
1745 |Args { resumable, .. }| {
1746 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1747 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1748 let lanes2: [i8; 16] = to_lanes(data2);
1749 let lanes1: [i8; 16] = to_lanes(data1);
1750 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
1751 resumable
1752 .stack
1753 .push_value(Value::V128(from_lanes(result)))?;
1754 Ok(ControlFlow::Continue(()))
1755 }
1756}
1757define_instruction_fn! {
1758 i16x8_gt_s,
1759 fuel_check = flat_fd(opcode::fd_extensions::I16X8_GT_S),
1760 |Args { resumable, .. }| {
1761 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1762 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1763 let lanes2: [i16; 8] = to_lanes(data2);
1764 let lanes1: [i16; 8] = to_lanes(data1);
1765 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
1766 resumable
1767 .stack
1768 .push_value(Value::V128(from_lanes(result)))?;
1769 Ok(ControlFlow::Continue(()))
1770 }
1771}
1772define_instruction_fn! {
1773 i32x4_gt_s,
1774 fuel_check = flat_fd(opcode::fd_extensions::I32X4_GT_S),
1775 |Args { resumable, .. }| {
1776 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1777 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1778 let lanes2: [i32; 4] = to_lanes(data2);
1779 let lanes1: [i32; 4] = to_lanes(data1);
1780 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
1781 resumable
1782 .stack
1783 .push_value(Value::V128(from_lanes(result)))?;
1784 Ok(ControlFlow::Continue(()))
1785 }
1786}
1787define_instruction_fn! {
1788 i64x2_gt_s,
1789 fuel_check = flat_fd(opcode::fd_extensions::I64X2_GT_S),
1790 |Args { resumable, .. }| {
1791 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1792 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1793 let lanes2: [i64; 2] = to_lanes(data2);
1794 let lanes1: [i64; 2] = to_lanes(data1);
1795 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
1796 resumable
1797 .stack
1798 .push_value(Value::V128(from_lanes(result)))?;
1799 Ok(ControlFlow::Continue(()))
1800 }
1801}
1802define_instruction_fn! {
1803 i8x16_gt_u,
1804 fuel_check = flat_fd(opcode::fd_extensions::I8X16_GT_U),
1805 |Args { resumable, .. }| {
1806 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1807 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1808 let lanes2: [u8; 16] = to_lanes(data2);
1809 let lanes1: [u8; 16] = to_lanes(data1);
1810 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i8).neg());
1811 resumable
1812 .stack
1813 .push_value(Value::V128(from_lanes(result)))?;
1814 Ok(ControlFlow::Continue(()))
1815 }
1816}
1817define_instruction_fn! {
1818 i16x8_gt_u,
1819 fuel_check = flat_fd(opcode::fd_extensions::I16X8_GT_U),
1820 |Args { resumable, .. }| {
1821 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1822 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1823 let lanes2: [u16; 8] = to_lanes(data2);
1824 let lanes1: [u16; 8] = to_lanes(data1);
1825 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i16).neg());
1826 resumable
1827 .stack
1828 .push_value(Value::V128(from_lanes(result)))?;
1829 Ok(ControlFlow::Continue(()))
1830 }
1831}
1832define_instruction_fn! {
1833 i32x4_gt_u,
1834 fuel_check = flat_fd(opcode::fd_extensions::I32X4_GT_U),
1835 |Args { resumable, .. }| {
1836 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1837 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1838 let lanes2: [u32; 4] = to_lanes(data2);
1839 let lanes1: [u32; 4] = to_lanes(data1);
1840 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
1841 resumable
1842 .stack
1843 .push_value(Value::V128(from_lanes(result)))?;
1844 Ok(ControlFlow::Continue(()))
1845 }
1846}
1847define_instruction_fn! {
1848 i8x16_le_s,
1849 fuel_check = flat_fd(opcode::fd_extensions::I8X16_LE_S),
1850 |Args { resumable, .. }| {
1851 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1852 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1853 let lanes2: [i8; 16] = to_lanes(data2);
1854 let lanes1: [i8; 16] = to_lanes(data1);
1855 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
1856 resumable
1857 .stack
1858 .push_value(Value::V128(from_lanes(result)))?;
1859 Ok(ControlFlow::Continue(()))
1860 }
1861}
1862define_instruction_fn! {
1863 i16x8_le_s,
1864 fuel_check = flat_fd(opcode::fd_extensions::I16X8_LE_S),
1865 |Args { resumable, .. }| {
1866 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1867 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1868 let lanes2: [i16; 8] = to_lanes(data2);
1869 let lanes1: [i16; 8] = to_lanes(data1);
1870 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
1871 resumable
1872 .stack
1873 .push_value(Value::V128(from_lanes(result)))?;
1874 Ok(ControlFlow::Continue(()))
1875 }
1876}
1877define_instruction_fn! {
1878 i32x4_le_s,
1879 fuel_check = flat_fd(opcode::fd_extensions::I32X4_LE_S),
1880 |Args { resumable, .. }| {
1881 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1882 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1883 let lanes2: [i32; 4] = to_lanes(data2);
1884 let lanes1: [i32; 4] = to_lanes(data1);
1885 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
1886 resumable
1887 .stack
1888 .push_value(Value::V128(from_lanes(result)))?;
1889 Ok(ControlFlow::Continue(()))
1890 }
1891}
1892define_instruction_fn! {
1893 i64x2_le_s,
1894 fuel_check = flat_fd(opcode::fd_extensions::I64X2_LE_S),
1895 |Args { resumable, .. }| {
1896 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1897 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1898 let lanes2: [i64; 2] = to_lanes(data2);
1899 let lanes1: [i64; 2] = to_lanes(data1);
1900 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
1901 resumable
1902 .stack
1903 .push_value(Value::V128(from_lanes(result)))?;
1904 Ok(ControlFlow::Continue(()))
1905 }
1906}
1907define_instruction_fn! {
1908 i8x16_le_u,
1909 fuel_check = flat_fd(opcode::fd_extensions::I8X16_LE_U),
1910 |Args { resumable, .. }| {
1911 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1912 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1913 let lanes2: [u8; 16] = to_lanes(data2);
1914 let lanes1: [u8; 16] = to_lanes(data1);
1915 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i8).neg());
1916 resumable
1917 .stack
1918 .push_value(Value::V128(from_lanes(result)))?;
1919 Ok(ControlFlow::Continue(()))
1920 }
1921}
1922define_instruction_fn! {
1923 i16x8_le_u,
1924 fuel_check = flat_fd(opcode::fd_extensions::I16X8_LE_U),
1925 |Args { resumable, .. }| {
1926 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1927 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1928 let lanes2: [u16; 8] = to_lanes(data2);
1929 let lanes1: [u16; 8] = to_lanes(data1);
1930 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i16).neg());
1931 resumable
1932 .stack
1933 .push_value(Value::V128(from_lanes(result)))?;
1934 Ok(ControlFlow::Continue(()))
1935 }
1936}
1937define_instruction_fn! {
1938 i32x4_le_u,
1939 fuel_check = flat_fd(opcode::fd_extensions::I32X4_LE_U),
1940 |Args { resumable, .. }| {
1941 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1942 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1943 let lanes2: [u32; 4] = to_lanes(data2);
1944 let lanes1: [u32; 4] = to_lanes(data1);
1945 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
1946 resumable
1947 .stack
1948 .push_value(Value::V128(from_lanes(result)))?;
1949 Ok(ControlFlow::Continue(()))
1950 }
1951}
1952
1953define_instruction_fn! {
1954 i8x16_ge_s,
1955 fuel_check = flat_fd(opcode::fd_extensions::I8X16_GE_S),
1956 |Args { resumable, .. }| {
1957 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1958 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1959 let lanes2: [i8; 16] = to_lanes(data2);
1960 let lanes1: [i8; 16] = to_lanes(data1);
1961 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
1962 resumable
1963 .stack
1964 .push_value(Value::V128(from_lanes(result)))?;
1965 Ok(ControlFlow::Continue(()))
1966 }
1967}
1968define_instruction_fn! {
1969 i16x8_ge_s,
1970 fuel_check = flat_fd(opcode::fd_extensions::I16X8_GE_S),
1971 |Args { resumable, .. }| {
1972 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1973 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1974 let lanes2: [i16; 8] = to_lanes(data2);
1975 let lanes1: [i16; 8] = to_lanes(data1);
1976 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
1977 resumable
1978 .stack
1979 .push_value(Value::V128(from_lanes(result)))?;
1980 Ok(ControlFlow::Continue(()))
1981 }
1982}
1983define_instruction_fn! {
1984 i32x4_ge_s,
1985 fuel_check = flat_fd(opcode::fd_extensions::I32X4_GE_S),
1986 |Args { resumable, .. }| {
1987 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1988 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
1989 let lanes2: [i32; 4] = to_lanes(data2);
1990 let lanes1: [i32; 4] = to_lanes(data1);
1991 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
1992 resumable
1993 .stack
1994 .push_value(Value::V128(from_lanes(result)))?;
1995 Ok(ControlFlow::Continue(()))
1996 }
1997}
1998define_instruction_fn! {
1999 i64x2_ge_s,
2000 fuel_check = flat_fd(opcode::fd_extensions::I64X2_GE_S),
2001 |Args { resumable, .. }| {
2002 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2003 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2004 let lanes2: [i64; 2] = to_lanes(data2);
2005 let lanes1: [i64; 2] = to_lanes(data1);
2006 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
2007 resumable
2008 .stack
2009 .push_value(Value::V128(from_lanes(result)))?;
2010 Ok(ControlFlow::Continue(()))
2011 }
2012}
2013define_instruction_fn! {
2014 i8x16_ge_u,
2015 fuel_check = flat_fd(opcode::fd_extensions::I8X16_GE_U),
2016 |Args { resumable, .. }| {
2017 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2018 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2019 let lanes2: [u8; 16] = to_lanes(data2);
2020 let lanes1: [u8; 16] = to_lanes(data1);
2021 let result: [i8; 16] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i8).neg());
2022 resumable
2023 .stack
2024 .push_value(Value::V128(from_lanes(result)))?;
2025 Ok(ControlFlow::Continue(()))
2026 }
2027}
2028define_instruction_fn! {
2029 i16x8_ge_u,
2030 fuel_check = flat_fd(opcode::fd_extensions::I16X8_GE_U),
2031 |Args { resumable, .. }| {
2032 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2033 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2034 let lanes2: [u16; 8] = to_lanes(data2);
2035 let lanes1: [u16; 8] = to_lanes(data1);
2036 let result: [i16; 8] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i16).neg());
2037 resumable
2038 .stack
2039 .push_value(Value::V128(from_lanes(result)))?;
2040 Ok(ControlFlow::Continue(()))
2041 }
2042}
2043define_instruction_fn! {
2044 i32x4_ge_u,
2045 fuel_check = flat_fd(opcode::fd_extensions::I32X4_GE_U),
2046 |Args { resumable, .. }| {
2047 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2048 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2049 let lanes2: [u32; 4] = to_lanes(data2);
2050 let lanes1: [u32; 4] = to_lanes(data1);
2051 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
2052 resumable
2053 .stack
2054 .push_value(Value::V128(from_lanes(result)))?;
2055 Ok(ControlFlow::Continue(()))
2056 }
2057}
2058define_instruction_fn! {
2060 f32x4_eq,
2061 fuel_check = flat_fd(opcode::fd_extensions::F32X4_EQ),
2062 |Args { resumable, .. }| {
2063 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2064 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2065 let lanes2: [F32; 4] = to_lanes(data2);
2066 let lanes1: [F32; 4] = to_lanes(data1);
2067 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i32).neg());
2068 resumable
2069 .stack
2070 .push_value(Value::V128(from_lanes(result)))?;
2071 Ok(ControlFlow::Continue(()))
2072 }
2073}
2074define_instruction_fn! {
2075 f64x2_eq,
2076 fuel_check = flat_fd(opcode::fd_extensions::F64X2_EQ),
2077 |Args { resumable, .. }| {
2078 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2079 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2080 let lanes2: [F64; 2] = to_lanes(data2);
2081 let lanes1: [F64; 2] = to_lanes(data1);
2082 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] == lanes2[i]) as i64).neg());
2083 resumable
2084 .stack
2085 .push_value(Value::V128(from_lanes(result)))?;
2086 Ok(ControlFlow::Continue(()))
2087 }
2088}
2089define_instruction_fn! {
2090 f32x4_ne,
2091 fuel_check = flat_fd(opcode::fd_extensions::F32X4_NE),
2092 |Args { resumable, .. }| {
2093 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2094 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2095 let lanes2: [F32; 4] = to_lanes(data2);
2096 let lanes1: [F32; 4] = to_lanes(data1);
2097 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i32).neg());
2098 resumable
2099 .stack
2100 .push_value(Value::V128(from_lanes(result)))?;
2101 Ok(ControlFlow::Continue(()))
2102 }
2103}
2104define_instruction_fn! {
2105 f64x2_ne,
2106 fuel_check = flat_fd(opcode::fd_extensions::F64X2_NE),
2107 |Args { resumable, .. }| {
2108 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2109 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2110 let lanes2: [F64; 2] = to_lanes(data2);
2111 let lanes1: [F64; 2] = to_lanes(data1);
2112 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] != lanes2[i]) as i64).neg());
2113 resumable
2114 .stack
2115 .push_value(Value::V128(from_lanes(result)))?;
2116 Ok(ControlFlow::Continue(()))
2117 }
2118}
2119define_instruction_fn! {
2120 f32x4_lt,
2121 fuel_check = flat_fd(opcode::fd_extensions::F32X4_LT),
2122 |Args { resumable, .. }| {
2123 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2124 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2125 let lanes2: [F32; 4] = to_lanes(data2);
2126 let lanes1: [F32; 4] = to_lanes(data1);
2127 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i32).neg());
2128 resumable
2129 .stack
2130 .push_value(Value::V128(from_lanes(result)))?;
2131 Ok(ControlFlow::Continue(()))
2132 }
2133}
2134define_instruction_fn! {
2135 f64x2_lt,
2136 fuel_check = flat_fd(opcode::fd_extensions::F64X2_LT),
2137 |Args { resumable, .. }| {
2138 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2139 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2140 let lanes2: [F64; 2] = to_lanes(data2);
2141 let lanes1: [F64; 2] = to_lanes(data1);
2142 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] < lanes2[i]) as i64).neg());
2143 resumable
2144 .stack
2145 .push_value(Value::V128(from_lanes(result)))?;
2146 Ok(ControlFlow::Continue(()))
2147 }
2148}
2149define_instruction_fn! {
2150 f32x4_gt,
2151 fuel_check = flat_fd(opcode::fd_extensions::F32X4_GT),
2152 |Args { resumable, .. }| {
2153 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2154 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2155 let lanes2: [F32; 4] = to_lanes(data2);
2156 let lanes1: [F32; 4] = to_lanes(data1);
2157 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i32).neg());
2158 resumable
2159 .stack
2160 .push_value(Value::V128(from_lanes(result)))?;
2161 Ok(ControlFlow::Continue(()))
2162 }
2163}
2164define_instruction_fn! {
2165 f64x2_gt,
2166 fuel_check = flat_fd(opcode::fd_extensions::F64X2_GT),
2167 |Args { resumable, .. }| {
2168 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2169 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2170 let lanes2: [F64; 2] = to_lanes(data2);
2171 let lanes1: [F64; 2] = to_lanes(data1);
2172 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] > lanes2[i]) as i64).neg());
2173 resumable
2174 .stack
2175 .push_value(Value::V128(from_lanes(result)))?;
2176 Ok(ControlFlow::Continue(()))
2177 }
2178}
2179define_instruction_fn! {
2180 f32x4_le,
2181 fuel_check = flat_fd(opcode::fd_extensions::F32X4_LE),
2182 |Args { resumable, .. }| {
2183 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2184 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2185 let lanes2: [F32; 4] = to_lanes(data2);
2186 let lanes1: [F32; 4] = to_lanes(data1);
2187 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i32).neg());
2188 resumable
2189 .stack
2190 .push_value(Value::V128(from_lanes(result)))?;
2191 Ok(ControlFlow::Continue(()))
2192 }
2193}
2194define_instruction_fn! {
2195 f64x2_le,
2196 fuel_check = flat_fd(opcode::fd_extensions::F64X2_LE),
2197 |Args { resumable, .. }| {
2198 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2199 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2200 let lanes2: [F64; 2] = to_lanes(data2);
2201 let lanes1: [F64; 2] = to_lanes(data1);
2202 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] <= lanes2[i]) as i64).neg());
2203 resumable
2204 .stack
2205 .push_value(Value::V128(from_lanes(result)))?;
2206 Ok(ControlFlow::Continue(()))
2207 }
2208}
2209define_instruction_fn! {
2210 f32x4_ge,
2211 fuel_check = flat_fd(opcode::fd_extensions::F32X4_GE),
2212 |Args { resumable, .. }| {
2213 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2214 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2215 let lanes2: [F32; 4] = to_lanes(data2);
2216 let lanes1: [F32; 4] = to_lanes(data1);
2217 let result: [i32; 4] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i32).neg());
2218 resumable
2219 .stack
2220 .push_value(Value::V128(from_lanes(result)))?;
2221 Ok(ControlFlow::Continue(()))
2222 }
2223}
2224define_instruction_fn! {
2225 f64x2_ge,
2226 fuel_check = flat_fd(opcode::fd_extensions::F64X2_GE),
2227 |Args { resumable, .. }| {
2228 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2229 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2230 let lanes2: [F64; 2] = to_lanes(data2);
2231 let lanes1: [F64; 2] = to_lanes(data1);
2232 let result: [i64; 2] = array::from_fn(|i| ((lanes1[i] >= lanes2[i]) as i64).neg());
2233 resumable
2234 .stack
2235 .push_value(Value::V128(from_lanes(result)))?;
2236 Ok(ControlFlow::Continue(()))
2237 }
2238}
2239
2240define_instruction_fn! {
2242 i8x16_shl,
2243 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SHL),
2244 |Args { resumable, .. }| {
2245 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2246 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2247 let lanes: [u8; 16] = to_lanes(data);
2248 let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shl(shift));
2249 resumable
2250 .stack
2251 .push_value(Value::V128(from_lanes(result)))?;
2252 Ok(ControlFlow::Continue(()))
2253 }
2254}
2255define_instruction_fn! {
2256 i16x8_shl,
2257 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SHL),
2258 |Args { resumable, .. }| {
2259 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2260 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2261 let lanes: [u16; 8] = to_lanes(data);
2262 let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shl(shift));
2263 resumable
2264 .stack
2265 .push_value(Value::V128(from_lanes(result)))?;
2266 Ok(ControlFlow::Continue(()))
2267 }
2268}
2269define_instruction_fn! {
2270 i32x4_shl,
2271 fuel_check = flat_fd(opcode::fd_extensions::I32X4_SHL),
2272 |Args { resumable, .. }| {
2273 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2274 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2275 let lanes: [u32; 4] = to_lanes(data);
2276 let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shl(shift));
2277 resumable
2278 .stack
2279 .push_value(Value::V128(from_lanes(result)))?;
2280 Ok(ControlFlow::Continue(()))
2281 }
2282}
2283define_instruction_fn! {
2284 i64x2_shl,
2285 fuel_check = flat_fd(opcode::fd_extensions::I64X2_SHL),
2286 |Args { resumable, .. }| {
2287 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2288 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2289 let lanes: [u64; 2] = to_lanes(data);
2290 let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shl(shift));
2291 resumable
2292 .stack
2293 .push_value(Value::V128(from_lanes(result)))?;
2294 Ok(ControlFlow::Continue(()))
2295 }
2296}
2297define_instruction_fn! {
2298 i8x16_shr_s,
2299 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SHR_S),
2300 |Args { resumable, .. }| {
2301 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2302 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2303 let lanes: [i8; 16] = to_lanes(data);
2304 let result: [i8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
2305 resumable
2306 .stack
2307 .push_value(Value::V128(from_lanes(result)))?;
2308 Ok(ControlFlow::Continue(()))
2309 }
2310}
2311define_instruction_fn! {
2312 i8x16_shr_u,
2313 fuel_check = flat_fd(opcode::fd_extensions::I8X16_SHR_U),
2314 |Args { resumable, .. }| {
2315 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2316 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2317 let lanes: [u8; 16] = to_lanes(data);
2318 let result: [u8; 16] = lanes.map(|lane| lane.wrapping_shr(shift));
2319 resumable
2320 .stack
2321 .push_value(Value::V128(from_lanes(result)))?;
2322 Ok(ControlFlow::Continue(()))
2323 }
2324}
2325define_instruction_fn! {
2326 i16x8_shr_s,
2327 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SHR_S),
2328 |Args { resumable, .. }| {
2329 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2330 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2331 let lanes: [i16; 8] = to_lanes(data);
2332 let result: [i16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
2333 resumable
2334 .stack
2335 .push_value(Value::V128(from_lanes(result)))?;
2336 Ok(ControlFlow::Continue(()))
2337 }
2338}
2339define_instruction_fn! {
2340 i16x8_shr_u,
2341 fuel_check = flat_fd(opcode::fd_extensions::I16X8_SHR_U),
2342 |Args { resumable, .. }| {
2343 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2344 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2345 let lanes: [u16; 8] = to_lanes(data);
2346 let result: [u16; 8] = lanes.map(|lane| lane.wrapping_shr(shift));
2347 resumable
2348 .stack
2349 .push_value(Value::V128(from_lanes(result)))?;
2350 Ok(ControlFlow::Continue(()))
2351 }
2352}
2353define_instruction_fn! {
2354 i32x4_shr_s,
2355 fuel_check = flat_fd(opcode::fd_extensions::I32X4_SHR_S),
2356 |Args { resumable, .. }| {
2357 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2358 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2359 let lanes: [i32; 4] = to_lanes(data);
2360 let result: [i32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
2361 resumable
2362 .stack
2363 .push_value(Value::V128(from_lanes(result)))?;
2364 Ok(ControlFlow::Continue(()))
2365 }
2366}
2367define_instruction_fn! {
2368 i32x4_shr_u,
2369 fuel_check = flat_fd(opcode::fd_extensions::I32X4_SHR_U),
2370 |Args { resumable, .. }| {
2371 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2372 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2373 let lanes: [u32; 4] = to_lanes(data);
2374 let result: [u32; 4] = lanes.map(|lane| lane.wrapping_shr(shift));
2375 resumable
2376 .stack
2377 .push_value(Value::V128(from_lanes(result)))?;
2378 Ok(ControlFlow::Continue(()))
2379 }
2380}
2381define_instruction_fn! {
2382 i64x2_shr_s,
2383 fuel_check = flat_fd(opcode::fd_extensions::I64X2_SHR_S),
2384 |Args { resumable, .. }| {
2385 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2386 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2387 let lanes: [i64; 2] = to_lanes(data);
2388 let result: [i64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
2389 resumable
2390 .stack
2391 .push_value(Value::V128(from_lanes(result)))?;
2392 Ok(ControlFlow::Continue(()))
2393 }
2394}
2395define_instruction_fn! {
2396 i64x2_shr_u,
2397 fuel_check = flat_fd(opcode::fd_extensions::I64X2_SHR_U),
2398 |Args { resumable, .. }| {
2399 let shift: u32 = resumable.stack.pop_value().try_into().unwrap_validated();
2400 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2401 let lanes: [u64; 2] = to_lanes(data);
2402 let result: [u64; 2] = lanes.map(|lane| lane.wrapping_shr(shift));
2403 resumable
2404 .stack
2405 .push_value(Value::V128(from_lanes(result)))?;
2406 Ok(ControlFlow::Continue(()))
2407 }
2408}
2409
2410define_instruction_fn! {
2412 i8x16_all_true,
2413 fuel_check = flat_fd(opcode::fd_extensions::I8X16_ALL_TRUE),
2414 |Args { resumable, .. }| {
2415 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2416 let lanes: [u8; 16] = to_lanes(data);
2417 let all_true = lanes.into_iter().all(|lane| lane != 0);
2418 resumable.stack.push_value(Value::I32(all_true as u32))?;
2419 Ok(ControlFlow::Continue(()))
2420 }
2421}
2422define_instruction_fn! {
2423 i16x8_all_true,
2424 fuel_check = flat_fd(opcode::fd_extensions::I16X8_ALL_TRUE),
2425 |Args { resumable, .. }| {
2426 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2427 let lanes: [u16; 8] = to_lanes(data);
2428 let all_true = lanes.into_iter().all(|lane| lane != 0);
2429 resumable.stack.push_value(Value::I32(all_true as u32))?;
2430 Ok(ControlFlow::Continue(()))
2431 }
2432}
2433define_instruction_fn! {
2434 i32x4_all_true,
2435 fuel_check = flat_fd(opcode::fd_extensions::I32X4_ALL_TRUE),
2436 |Args { resumable, .. }| {
2437 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2438 let lanes: [u32; 4] = to_lanes(data);
2439 let all_true = lanes.into_iter().all(|lane| lane != 0);
2440 resumable.stack.push_value(Value::I32(all_true as u32))?;
2441 Ok(ControlFlow::Continue(()))
2442 }
2443}
2444define_instruction_fn! {
2445 i64x2_all_true,
2446 fuel_check = flat_fd(opcode::fd_extensions::I64X2_ALL_TRUE),
2447 |Args { resumable, .. }| {
2448 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2449 let lanes: [u64; 2] = to_lanes(data);
2450 let all_true = lanes.into_iter().all(|lane| lane != 0);
2451 resumable.stack.push_value(Value::I32(all_true as u32))?;
2452 Ok(ControlFlow::Continue(()))
2453 }
2454}
2455
2456define_instruction_fn! {
2458 i8x16_bitmask,
2459 fuel_check = flat_fd(opcode::fd_extensions::I8X16_BITMASK),
2460 |Args { resumable, .. }| {
2461 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2462 let lanes: [i8; 16] = to_lanes(data);
2463 let bits = lanes.map(|lane| lane < 0);
2464 let bitmask = bits
2465 .into_iter()
2466 .enumerate()
2467 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
2468 resumable.stack.push_value(Value::I32(bitmask))?;
2469 Ok(ControlFlow::Continue(()))
2470 }
2471}
2472define_instruction_fn! {
2473 i16x8_bitmask,
2474 fuel_check = flat_fd(opcode::fd_extensions::I16X8_BITMASK),
2475 |Args { resumable, .. }| {
2476 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2477 let lanes: [i16; 8] = to_lanes(data);
2478 let bits = lanes.map(|lane| lane < 0);
2479 let bitmask = bits
2480 .into_iter()
2481 .enumerate()
2482 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
2483 resumable.stack.push_value(Value::I32(bitmask))?;
2484 Ok(ControlFlow::Continue(()))
2485 }
2486}
2487define_instruction_fn! {
2488 i32x4_bitmask,
2489 fuel_check = flat_fd(opcode::fd_extensions::I32X4_BITMASK),
2490 |Args { resumable, .. }| {
2491 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2492 let lanes: [i32; 4] = to_lanes(data);
2493 let bits = lanes.map(|lane| lane < 0);
2494 let bitmask = bits
2495 .into_iter()
2496 .enumerate()
2497 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
2498 resumable.stack.push_value(Value::I32(bitmask))?;
2499 Ok(ControlFlow::Continue(()))
2500 }
2501}
2502define_instruction_fn! {
2503 i64x2_bitmask,
2504 fuel_check = flat_fd(opcode::fd_extensions::I64X2_BITMASK),
2505 |Args { resumable, .. }| {
2506 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2507 let lanes: [i64; 2] = to_lanes(data);
2508 let bits = lanes.map(|lane| lane < 0);
2509 let bitmask = bits
2510 .into_iter()
2511 .enumerate()
2512 .fold(0u32, |acc, (i, bit)| acc | ((bit as u32) << i));
2513 resumable.stack.push_value(Value::I32(bitmask))?;
2514 Ok(ControlFlow::Continue(()))
2515 }
2516}
2517
2518define_instruction_fn! {
2520 i8x16_narrow_i16x8_s,
2521 fuel_check = flat_fd(opcode::fd_extensions::I8X16_NARROW_I16X8_S),
2522 |Args { resumable, .. }| {
2523 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2524 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2525 let lanes2: [i16; 8] = to_lanes(data2);
2526 let lanes1: [i16; 8] = to_lanes(data1);
2527 let mut concatenated_narrowed_lanes = lanes1
2528 .into_iter()
2529 .chain(lanes2)
2530 .map(|lane| lane.clamp(i8::MIN as i16, i8::MAX as i16) as i8);
2531 let result: [i8; 16] = array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
2532 resumable
2533 .stack
2534 .push_value(Value::V128(from_lanes(result)))?;
2535 Ok(ControlFlow::Continue(()))
2536 }
2537}
2538define_instruction_fn! {
2539 i8x16_narrow_i16x8_u,
2540 fuel_check = flat_fd(opcode::fd_extensions::I8X16_NARROW_I16X8_U),
2541 |Args { resumable, .. }| {
2542 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2543 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2544 let lanes2: [i16; 8] = to_lanes(data2);
2545 let lanes1: [i16; 8] = to_lanes(data1);
2546 let mut concatenated_narrowed_lanes = lanes1
2547 .into_iter()
2548 .chain(lanes2)
2549 .map(|lane| lane.clamp(u8::MIN as i16, u8::MAX as i16) as u8);
2550 let result: [u8; 16] = array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
2551 resumable
2552 .stack
2553 .push_value(Value::V128(from_lanes(result)))?;
2554 Ok(ControlFlow::Continue(()))
2555 }
2556}
2557define_instruction_fn! {
2558 i16x8_narrow_i32x4_s,
2559 fuel_check = flat_fd(opcode::fd_extensions::I16X8_NARROW_I32X4_S),
2560 |Args { resumable, .. }| {
2561 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2562 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2563 let lanes2: [i32; 4] = to_lanes(data2);
2564 let lanes1: [i32; 4] = to_lanes(data1);
2565 let mut concatenated_narrowed_lanes = lanes1
2566 .into_iter()
2567 .chain(lanes2)
2568 .map(|lane| lane.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
2569 let result: [i16; 8] = array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
2570 resumable
2571 .stack
2572 .push_value(Value::V128(from_lanes(result)))?;
2573 Ok(ControlFlow::Continue(()))
2574 }
2575}
2576define_instruction_fn! {
2577 i16x8_narrow_i32x4_u,
2578 fuel_check = flat_fd(opcode::fd_extensions::I16X8_NARROW_I32X4_U),
2579 |Args { resumable, .. }| {
2580 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2581 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2582 let lanes2: [i32; 4] = to_lanes(data2);
2583 let lanes1: [i32; 4] = to_lanes(data1);
2584 let mut concatenated_narrowed_lanes = lanes1
2585 .into_iter()
2586 .chain(lanes2)
2587 .map(|lane| lane.clamp(u16::MIN as i32, u16::MAX as i32) as u16);
2588 let result: [u16; 8] = array::from_fn(|_| concatenated_narrowed_lanes.next().unwrap());
2589 resumable
2590 .stack
2591 .push_value(Value::V128(from_lanes(result)))?;
2592 Ok(ControlFlow::Continue(()))
2593 }
2594}
2595
2596define_instruction_fn! {
2598 i32x4_trunc_sat_f32x4_s,
2599 fuel_check = flat_fd(opcode::fd_extensions::I32X4_TRUNC_SAT_F32X4_S),
2600 |Args { resumable, .. }| {
2601 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2602 let lanes: [F32; 4] = to_lanes(data);
2603 let result = lanes.map(|lane| {
2604 if lane.is_nan() {
2605 0
2606 } else if lane.is_negative_infinity() {
2607 i32::MIN
2608 } else if lane.is_infinity() {
2609 i32::MAX
2610 } else {
2611 lane.as_i32()
2612 }
2613 });
2614 resumable
2615 .stack
2616 .push_value(Value::V128(from_lanes(result)))?;
2617 Ok(ControlFlow::Continue(()))
2618 }
2619}
2620define_instruction_fn! {
2621 i32x4_trunc_sat_f32x4_u,
2622 fuel_check = flat_fd(opcode::fd_extensions::I32X4_TRUNC_SAT_F32X4_U),
2623 |Args { resumable, .. }| {
2624 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2625 let lanes: [F32; 4] = to_lanes(data);
2626 let result = lanes.map(|lane| {
2627 if lane.is_nan() || lane.is_negative_infinity() {
2628 u32::MIN
2629 } else if lane.is_infinity() {
2630 u32::MAX
2631 } else {
2632 lane.as_u32()
2633 }
2634 });
2635 resumable
2636 .stack
2637 .push_value(Value::V128(from_lanes(result)))?;
2638 Ok(ControlFlow::Continue(()))
2639 }
2640}
2641define_instruction_fn! {
2642 f32x4_convert_i32x4_s,
2643 fuel_check = flat_fd(opcode::fd_extensions::F32X4_CONVERT_I32X4_S),
2644 |Args { resumable, .. }| {
2645 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2646 let lanes: [i32; 4] = to_lanes(data);
2647 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
2648 resumable
2649 .stack
2650 .push_value(Value::V128(from_lanes(result)))?;
2651 Ok(ControlFlow::Continue(()))
2652 }
2653}
2654define_instruction_fn! {
2655 f32x4_convert_i32x4_u,
2656 fuel_check = flat_fd(opcode::fd_extensions::F32X4_CONVERT_I32X4_U),
2657 |Args { resumable, .. }| {
2658 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2659 let lanes: [u32; 4] = to_lanes(data);
2660 let result: [F32; 4] = lanes.map(|lane| F32(lane as f32));
2661 resumable
2662 .stack
2663 .push_value(Value::V128(from_lanes(result)))?;
2664 Ok(ControlFlow::Continue(()))
2665 }
2666}
2667
2668define_instruction_fn! {
2670 i16x8_extend_high_i8x16_s,
2671 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTEND_HIGH_I8X16_S),
2672 |Args { resumable, .. }| {
2673 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2674 let lanes: [i8; 16] = to_lanes(data);
2675 let high_lanes: [i8; 8] = lanes[8..].try_into().unwrap();
2676 let result = high_lanes.map(|lane| lane as i16);
2677 resumable
2678 .stack
2679 .push_value(Value::V128(from_lanes(result)))?;
2680 Ok(ControlFlow::Continue(()))
2681 }
2682}
2683define_instruction_fn! {
2684 i16x8_extend_high_i8x16_u,
2685 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTEND_HIGH_I8X16_U),
2686 |Args { resumable, .. }| {
2687 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2688 let lanes: [u8; 16] = to_lanes(data);
2689 let high_lanes: [u8; 8] = lanes[8..].try_into().unwrap();
2690 let result = high_lanes.map(|lane| lane as u16);
2691 resumable
2692 .stack
2693 .push_value(Value::V128(from_lanes(result)))?;
2694 Ok(ControlFlow::Continue(()))
2695 }
2696}
2697define_instruction_fn! {
2698 i16x8_extend_low_i8x16_s,
2699 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTEND_LOW_I8X16_S),
2700 |Args { resumable, .. }| {
2701 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2702 let lanes: [i8; 16] = to_lanes(data);
2703 let low_lanes: [i8; 8] = lanes[..8].try_into().unwrap();
2704 let result = low_lanes.map(|lane| lane as i16);
2705 resumable
2706 .stack
2707 .push_value(Value::V128(from_lanes(result)))?;
2708 Ok(ControlFlow::Continue(()))
2709 }
2710}
2711define_instruction_fn! {
2712 i16x8_extend_low_i8x16_u,
2713 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTEND_LOW_I8X16_U),
2714 |Args { resumable, .. }| {
2715 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2716 let lanes: [u8; 16] = to_lanes(data);
2717 let low_lanes: [u8; 8] = lanes[..8].try_into().unwrap();
2718 let result = low_lanes.map(|lane| lane as u16);
2719 resumable
2720 .stack
2721 .push_value(Value::V128(from_lanes(result)))?;
2722 Ok(ControlFlow::Continue(()))
2723 }
2724}
2725define_instruction_fn! {
2726 i32x4_extend_high_i16x8_s,
2727 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTEND_HIGH_I16X8_S),
2728 |Args { resumable, .. }| {
2729 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2730 let lanes: [i16; 8] = to_lanes(data);
2731 let high_lanes: [i16; 4] = lanes[4..].try_into().unwrap();
2732 let result = high_lanes.map(|lane| lane as i32);
2733 resumable
2734 .stack
2735 .push_value(Value::V128(from_lanes(result)))?;
2736 Ok(ControlFlow::Continue(()))
2737 }
2738}
2739define_instruction_fn! {
2740 i32x4_extend_high_i16x8_u,
2741 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTEND_HIGH_I16X8_U),
2742 |Args { resumable, .. }| {
2743 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2744 let lanes: [u16; 8] = to_lanes(data);
2745 let high_lanes: [u16; 4] = lanes[4..].try_into().unwrap();
2746 let result = high_lanes.map(|lane| lane as u32);
2747 resumable
2748 .stack
2749 .push_value(Value::V128(from_lanes(result)))?;
2750 Ok(ControlFlow::Continue(()))
2751 }
2752}
2753define_instruction_fn! {
2754 i32x4_extend_low_i16x8_s,
2755 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTEND_LOW_I16X8_S),
2756 |Args { resumable, .. }| {
2757 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2758 let lanes: [i16; 8] = to_lanes(data);
2759 let low_lanes: [i16; 4] = lanes[..4].try_into().unwrap();
2760 let result = low_lanes.map(|lane| lane as i32);
2761 resumable
2762 .stack
2763 .push_value(Value::V128(from_lanes(result)))?;
2764 Ok(ControlFlow::Continue(()))
2765 }
2766}
2767define_instruction_fn! {
2768 i32x4_extend_low_i16x8_u,
2769 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTEND_LOW_I16X8_U),
2770 |Args { resumable, .. }| {
2771 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2772 let lanes: [u16; 8] = to_lanes(data);
2773 let low_lanes: [u16; 4] = lanes[..4].try_into().unwrap();
2774 let result = low_lanes.map(|lane| lane as u32);
2775 resumable
2776 .stack
2777 .push_value(Value::V128(from_lanes(result)))?;
2778 Ok(ControlFlow::Continue(()))
2779 }
2780}
2781define_instruction_fn! {
2782 i64x2_extend_high_i32x4_s,
2783 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTEND_HIGH_I32X4_S),
2784 |Args { resumable, .. }| {
2785 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2786 let lanes: [i32; 4] = to_lanes(data);
2787 let high_lanes: [i32; 2] = lanes[2..].try_into().unwrap();
2788 let result = high_lanes.map(|lane| lane as i64);
2789 resumable
2790 .stack
2791 .push_value(Value::V128(from_lanes(result)))?;
2792 Ok(ControlFlow::Continue(()))
2793 }
2794}
2795define_instruction_fn! {
2796 i64x2_extend_high_i32x4_u,
2797 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTEND_HIGH_I32X4_U),
2798 |Args { resumable, .. }| {
2799 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2800 let lanes: [u32; 4] = to_lanes(data);
2801 let high_lanes: [u32; 2] = lanes[2..].try_into().unwrap();
2802 let result = high_lanes.map(|lane| lane as u64);
2803 resumable
2804 .stack
2805 .push_value(Value::V128(from_lanes(result)))?;
2806 Ok(ControlFlow::Continue(()))
2807 }
2808}
2809define_instruction_fn! {
2810 i64x2_extend_low_i32x4_s,
2811 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTEND_LOW_I32X4_S),
2812 |Args { resumable, .. }| {
2813 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2814 let lanes: [i32; 4] = to_lanes(data);
2815 let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
2816 let result = low_lanes.map(|lane| lane as i64);
2817 resumable
2818 .stack
2819 .push_value(Value::V128(from_lanes(result)))?;
2820 Ok(ControlFlow::Continue(()))
2821 }
2822}
2823define_instruction_fn! {
2824 i64x2_extend_low_i32x4_u,
2825 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTEND_LOW_I32X4_U),
2826 |Args { resumable, .. }| {
2827 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2828 let lanes: [u32; 4] = to_lanes(data);
2829 let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
2830 let result = low_lanes.map(|lane| lane as u64);
2831 resumable
2832 .stack
2833 .push_value(Value::V128(from_lanes(result)))?;
2834 Ok(ControlFlow::Continue(()))
2835 }
2836}
2837define_instruction_fn! {
2838 f64x2_convert_low_i32x4_s,
2839 fuel_check = flat_fd(opcode::fd_extensions::F64X2_CONVERT_LOW_I32X4_S),
2840 |Args { resumable, .. }| {
2841 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2842 let lanes: [i32; 4] = to_lanes(data);
2843 let low_lanes: [i32; 2] = lanes[..2].try_into().unwrap();
2844 let result = low_lanes.map(|lane| F64(lane as f64));
2845 resumable
2846 .stack
2847 .push_value(Value::V128(from_lanes(result)))?;
2848 Ok(ControlFlow::Continue(()))
2849 }
2850}
2851define_instruction_fn! {
2852 f64x2_convert_low_i32x4_u,
2853 fuel_check = flat_fd(opcode::fd_extensions::F64X2_CONVERT_LOW_I32X4_U),
2854 |Args { resumable, .. }| {
2855 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2856 let lanes: [u32; 4] = to_lanes(data);
2857 let low_lanes: [u32; 2] = lanes[..2].try_into().unwrap();
2858 let result = low_lanes.map(|lane| F64(lane as f64));
2859 resumable
2860 .stack
2861 .push_value(Value::V128(from_lanes(result)))?;
2862 Ok(ControlFlow::Continue(()))
2863 }
2864}
2865define_instruction_fn! {
2866 f64x2_promote_low_f32x4,
2867 fuel_check = flat_fd(opcode::fd_extensions::F64X2_PROMOTE_LOW_F32X4),
2868 |Args { resumable, .. }| {
2869 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2870 let lanes: [F32; 4] = to_lanes(data);
2871 let half_lanes: [F32; 2] = lanes[..2].try_into().unwrap();
2872 let result = half_lanes.map(|lane| lane.as_f64());
2873 resumable
2874 .stack
2875 .push_value(Value::V128(from_lanes(result)))?;
2876 Ok(ControlFlow::Continue(()))
2877 }
2878}
2879
2880define_instruction_fn! {
2882 i32x4_trunc_sat_f64x2_s_zero,
2883 fuel_check = flat_fd(opcode::fd_extensions::I32X4_TRUNC_SAT_F64X2_S_ZERO),
2884 |Args { resumable, .. }| {
2885 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2886 let lanes: [F64; 2] = to_lanes(data);
2887 let result = lanes.map(|lane| {
2888 if lane.is_nan() {
2889 0
2890 } else if lane.is_negative_infinity() {
2891 i32::MIN
2892 } else if lane.is_infinity() {
2893 i32::MAX
2894 } else {
2895 lane.as_i32()
2896 }
2897 });
2898 resumable
2899 .stack
2900 .push_value(Value::V128(from_lanes([result[0], result[1], 0, 0])))?;
2901 Ok(ControlFlow::Continue(()))
2902 }
2903}
2904define_instruction_fn! {
2905 i32x4_trunc_sat_f64x2_u_zero,
2906 fuel_check = flat_fd(opcode::fd_extensions::I32X4_TRUNC_SAT_F64X2_U_ZERO),
2907 |Args { resumable, .. }| {
2908 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2909 let lanes: [F64; 2] = to_lanes(data);
2910 let result = lanes.map(|lane| {
2911 if lane.is_nan() || lane.is_negative_infinity() {
2912 u32::MIN
2913 } else if lane.is_infinity() {
2914 u32::MAX
2915 } else {
2916 lane.as_u32()
2917 }
2918 });
2919 resumable
2920 .stack
2921 .push_value(Value::V128(from_lanes([result[0], result[1], 0, 0])))?;
2922 Ok(ControlFlow::Continue(()))
2923 }
2924}
2925define_instruction_fn! {
2926 f32x4_demote_f64x2_zero,
2927 fuel_check = flat_fd(opcode::fd_extensions::F32X4_DEMOTE_F64X2_ZERO),
2928 |Args { resumable, .. }| {
2929 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2930 let lanes = to_lanes::<8, 2, F64>(data);
2931 let half_lanes = lanes.map(|lane| lane.as_f32());
2932 let result = [half_lanes[0], half_lanes[1], F32(0.0), F32(0.0)];
2933 resumable
2934 .stack
2935 .push_value(Value::V128(from_lanes(result)))?;
2936 Ok(ControlFlow::Continue(()))
2937 }
2938}
2939
2940define_instruction_fn! {
2942 i32x4_dot_i16x8_s,
2943 fuel_check = flat_fd(opcode::fd_extensions::I32X4_DOT_I16X8_S),
2944 |Args { resumable, .. }| {
2945 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2946 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2947 let lanes1: [i16; 8] = to_lanes(data1);
2948 let lanes2: [i16; 8] = to_lanes(data2);
2949 let multiplied: [i32; 8] = array::from_fn(|i| {
2950 let v1 = lanes1[i] as i32;
2951 let v2 = lanes2[i] as i32;
2952 v1.wrapping_mul(v2)
2953 });
2954 let added: [i32; 4] = array::from_fn(|i| {
2955 let v1 = multiplied[2 * i];
2956 let v2 = multiplied[2 * i + 1];
2957 v1.wrapping_add(v2)
2958 });
2959 resumable.stack.push_value(Value::V128(from_lanes(added)))?;
2960 Ok(ControlFlow::Continue(()))
2961 }
2962}
2963
2964define_instruction_fn! {
2966 i16x8_extmul_high_i8x16_s,
2967 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTMUL_HIGH_I8X16_S),
2968 |Args { resumable, .. }| {
2969 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2970 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2971 let lanes1: [i8; 16] = to_lanes(data1);
2972 let lanes2: [i8; 16] = to_lanes(data2);
2973 let high_lanes1: [i8; 8] = lanes1[8..].try_into().unwrap();
2974 let high_lanes2: [i8; 8] = lanes2[8..].try_into().unwrap();
2975 let multiplied: [i16; 8] = array::from_fn(|i| {
2976 let v1 = high_lanes1[i] as i16;
2977 let v2 = high_lanes2[i] as i16;
2978 v1.wrapping_mul(v2)
2979 });
2980 resumable
2981 .stack
2982 .push_value(Value::V128(from_lanes(multiplied)))?;
2983 Ok(ControlFlow::Continue(()))
2984 }
2985}
2986define_instruction_fn! {
2987 i16x8_extmul_high_i8x16_u,
2988 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTMUL_HIGH_I8X16_U),
2989 |Args { resumable, .. }| {
2990 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2991 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
2992 let lanes1: [u8; 16] = to_lanes(data1);
2993 let lanes2: [u8; 16] = to_lanes(data2);
2994 let high_lanes1: [u8; 8] = lanes1[8..].try_into().unwrap();
2995 let high_lanes2: [u8; 8] = lanes2[8..].try_into().unwrap();
2996 let multiplied: [u16; 8] = array::from_fn(|i| {
2997 let v1 = high_lanes1[i] as u16;
2998 let v2 = high_lanes2[i] as u16;
2999 v1.wrapping_mul(v2)
3000 });
3001 resumable
3002 .stack
3003 .push_value(Value::V128(from_lanes(multiplied)))?;
3004 Ok(ControlFlow::Continue(()))
3005 }
3006}
3007define_instruction_fn! {
3008 i16x8_extmul_low_i8x16_s,
3009 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTMUL_LOW_I8X16_S),
3010 |Args { resumable, .. }| {
3011 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3012 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3013 let lanes1: [i8; 16] = to_lanes(data1);
3014 let lanes2: [i8; 16] = to_lanes(data2);
3015 let high_lanes1: [i8; 8] = lanes1[..8].try_into().unwrap();
3016 let high_lanes2: [i8; 8] = lanes2[..8].try_into().unwrap();
3017 let multiplied: [i16; 8] = array::from_fn(|i| {
3018 let v1 = high_lanes1[i] as i16;
3019 let v2 = high_lanes2[i] as i16;
3020 v1.wrapping_mul(v2)
3021 });
3022 resumable
3023 .stack
3024 .push_value(Value::V128(from_lanes(multiplied)))?;
3025 Ok(ControlFlow::Continue(()))
3026 }
3027}
3028define_instruction_fn! {
3029 i16x8_extmul_low_i8x16_u,
3030 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTMUL_LOW_I8X16_U),
3031 |Args { resumable, .. }| {
3032 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3033 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3034 let lanes1: [u8; 16] = to_lanes(data1);
3035 let lanes2: [u8; 16] = to_lanes(data2);
3036 let high_lanes1: [u8; 8] = lanes1[..8].try_into().unwrap();
3037 let high_lanes2: [u8; 8] = lanes2[..8].try_into().unwrap();
3038 let multiplied: [u16; 8] = array::from_fn(|i| {
3039 let v1 = high_lanes1[i] as u16;
3040 let v2 = high_lanes2[i] as u16;
3041 v1.wrapping_mul(v2)
3042 });
3043 resumable
3044 .stack
3045 .push_value(Value::V128(from_lanes(multiplied)))?;
3046 Ok(ControlFlow::Continue(()))
3047 }
3048}
3049define_instruction_fn! {
3050 i32x4_extmul_high_i16x8_s,
3051 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTMUL_HIGH_I16X8_S),
3052 |Args { resumable, .. }| {
3053 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3054 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3055 let lanes1: [i16; 8] = to_lanes(data1);
3056 let lanes2: [i16; 8] = to_lanes(data2);
3057 let high_lanes1: [i16; 4] = lanes1[4..].try_into().unwrap();
3058 let high_lanes2: [i16; 4] = lanes2[4..].try_into().unwrap();
3059 let multiplied: [i32; 4] = array::from_fn(|i| {
3060 let v1 = high_lanes1[i] as i32;
3061 let v2 = high_lanes2[i] as i32;
3062 v1.wrapping_mul(v2)
3063 });
3064 resumable
3065 .stack
3066 .push_value(Value::V128(from_lanes(multiplied)))?;
3067 Ok(ControlFlow::Continue(()))
3068 }
3069}
3070define_instruction_fn! {
3071 i32x4_extmul_high_i16x8_u,
3072 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTMUL_HIGH_I16X8_U),
3073 |Args { resumable, .. }| {
3074 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3075 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3076 let lanes1: [u16; 8] = to_lanes(data1);
3077 let lanes2: [u16; 8] = to_lanes(data2);
3078 let high_lanes1: [u16; 4] = lanes1[4..].try_into().unwrap();
3079 let high_lanes2: [u16; 4] = lanes2[4..].try_into().unwrap();
3080 let multiplied: [u32; 4] = array::from_fn(|i| {
3081 let v1 = high_lanes1[i] as u32;
3082 let v2 = high_lanes2[i] as u32;
3083 v1.wrapping_mul(v2)
3084 });
3085 resumable
3086 .stack
3087 .push_value(Value::V128(from_lanes(multiplied)))?;
3088 Ok(ControlFlow::Continue(()))
3089 }
3090}
3091define_instruction_fn! {
3092 i32x4_extmul_low_i16x8_s,
3093 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTMUL_LOW_I16X8_S),
3094 |Args { resumable, .. }| {
3095 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3096 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3097 let lanes1: [i16; 8] = to_lanes(data1);
3098 let lanes2: [i16; 8] = to_lanes(data2);
3099 let high_lanes1: [i16; 4] = lanes1[..4].try_into().unwrap();
3100 let high_lanes2: [i16; 4] = lanes2[..4].try_into().unwrap();
3101 let multiplied: [i32; 4] = array::from_fn(|i| {
3102 let v1 = high_lanes1[i] as i32;
3103 let v2 = high_lanes2[i] as i32;
3104 v1.wrapping_mul(v2)
3105 });
3106 resumable
3107 .stack
3108 .push_value(Value::V128(from_lanes(multiplied)))?;
3109 Ok(ControlFlow::Continue(()))
3110 }
3111}
3112define_instruction_fn! {
3113 i32x4_extmul_low_i16x8_u,
3114 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTMUL_LOW_I16X8_U),
3115 |Args { resumable, .. }| {
3116 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3117 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3118 let lanes1: [u16; 8] = to_lanes(data1);
3119 let lanes2: [u16; 8] = to_lanes(data2);
3120 let high_lanes1: [u16; 4] = lanes1[..4].try_into().unwrap();
3121 let high_lanes2: [u16; 4] = lanes2[..4].try_into().unwrap();
3122 let multiplied: [u32; 4] = array::from_fn(|i| {
3123 let v1 = high_lanes1[i] as u32;
3124 let v2 = high_lanes2[i] as u32;
3125 v1.wrapping_mul(v2)
3126 });
3127 resumable
3128 .stack
3129 .push_value(Value::V128(from_lanes(multiplied)))?;
3130 Ok(ControlFlow::Continue(()))
3131 }
3132}
3133define_instruction_fn! {
3134 i64x2_extmul_high_i32x4_s,
3135 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTMUL_HIGH_I32X4_S),
3136 |Args { resumable, .. }| {
3137 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3138 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3139 let lanes1: [i32; 4] = to_lanes(data1);
3140 let lanes2: [i32; 4] = to_lanes(data2);
3141 let high_lanes1: [i32; 2] = lanes1[2..].try_into().unwrap();
3142 let high_lanes2: [i32; 2] = lanes2[2..].try_into().unwrap();
3143 let multiplied: [i64; 2] = array::from_fn(|i| {
3144 let v1 = high_lanes1[i] as i64;
3145 let v2 = high_lanes2[i] as i64;
3146 v1.wrapping_mul(v2)
3147 });
3148 resumable
3149 .stack
3150 .push_value(Value::V128(from_lanes(multiplied)))?;
3151 Ok(ControlFlow::Continue(()))
3152 }
3153}
3154define_instruction_fn! {
3155 i64x2_extmul_high_i32x4_u,
3156 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTMUL_HIGH_I32X4_U),
3157 |Args { resumable, .. }| {
3158 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3159 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3160 let lanes1: [u32; 4] = to_lanes(data1);
3161 let lanes2: [u32; 4] = to_lanes(data2);
3162 let high_lanes1: [u32; 2] = lanes1[2..].try_into().unwrap();
3163 let high_lanes2: [u32; 2] = lanes2[2..].try_into().unwrap();
3164 let multiplied: [u64; 2] = array::from_fn(|i| {
3165 let v1 = high_lanes1[i] as u64;
3166 let v2 = high_lanes2[i] as u64;
3167 v1.wrapping_mul(v2)
3168 });
3169 resumable
3170 .stack
3171 .push_value(Value::V128(from_lanes(multiplied)))?;
3172 Ok(ControlFlow::Continue(()))
3173 }
3174}
3175define_instruction_fn! {
3176 i64x2_extmul_low_i32x4_s,
3177 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTMUL_LOW_I32X4_S),
3178 |Args { resumable, .. }| {
3179 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3180 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3181 let lanes1: [i32; 4] = to_lanes(data1);
3182 let lanes2: [i32; 4] = to_lanes(data2);
3183 let high_lanes1: [i32; 2] = lanes1[..2].try_into().unwrap();
3184 let high_lanes2: [i32; 2] = lanes2[..2].try_into().unwrap();
3185 let multiplied: [i64; 2] = array::from_fn(|i| {
3186 let v1 = high_lanes1[i] as i64;
3187 let v2 = high_lanes2[i] as i64;
3188 v1.wrapping_mul(v2)
3189 });
3190 resumable
3191 .stack
3192 .push_value(Value::V128(from_lanes(multiplied)))?;
3193 Ok(ControlFlow::Continue(()))
3194 }
3195}
3196define_instruction_fn! {
3197 i64x2_extmul_low_i32x4_u,
3198 fuel_check = flat_fd(opcode::fd_extensions::I64X2_EXTMUL_LOW_I32X4_U),
3199 |Args { resumable, .. }| {
3200 let data1: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3201 let data2: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3202 let lanes1: [u32; 4] = to_lanes(data1);
3203 let lanes2: [u32; 4] = to_lanes(data2);
3204 let high_lanes1: [u32; 2] = lanes1[..2].try_into().unwrap();
3205 let high_lanes2: [u32; 2] = lanes2[..2].try_into().unwrap();
3206 let multiplied: [u64; 2] = array::from_fn(|i| {
3207 let v1 = high_lanes1[i] as u64;
3208 let v2 = high_lanes2[i] as u64;
3209 v1.wrapping_mul(v2)
3210 });
3211 resumable
3212 .stack
3213 .push_value(Value::V128(from_lanes(multiplied)))?;
3214 Ok(ControlFlow::Continue(()))
3215 }
3216}
3217
3218define_instruction_fn! {
3220 i16x8_extadd_pairwise_i8x16_s,
3221 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTADD_PAIRWISE_I8X16_S),
3222 |Args { resumable, .. }| {
3223 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3224 let lanes: [i8; 16] = to_lanes(data);
3225 let added_pairwise: [i16; 8] = array::from_fn(|i| {
3226 let v1 = lanes[2 * i] as i16;
3227 let v2 = lanes[2 * i + 1] as i16;
3228 v1.wrapping_add(v2)
3229 });
3230 resumable
3231 .stack
3232 .push_value(Value::V128(from_lanes(added_pairwise)))?;
3233 Ok(ControlFlow::Continue(()))
3234 }
3235}
3236define_instruction_fn! {
3237 i16x8_extadd_pairwise_i8x16_u,
3238 fuel_check = flat_fd(opcode::fd_extensions::I16X8_EXTADD_PAIRWISE_I8X16_U),
3239 |Args { resumable, .. }| {
3240 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3241 let lanes: [u8; 16] = to_lanes(data);
3242 let added_pairwise: [u16; 8] = array::from_fn(|i| {
3243 let v1 = lanes[2 * i] as u16;
3244 let v2 = lanes[2 * i + 1] as u16;
3245 v1.wrapping_add(v2)
3246 });
3247 resumable
3248 .stack
3249 .push_value(Value::V128(from_lanes(added_pairwise)))?;
3250 Ok(ControlFlow::Continue(()))
3251 }
3252}
3253define_instruction_fn! {
3254 i32x4_extadd_pairwise_i16x8_s,
3255 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTADD_PAIRWISE_I16X8_S),
3256 |Args { resumable, .. }| {
3257 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3258 let lanes: [i16; 8] = to_lanes(data);
3259 let added_pairwise: [i32; 4] = array::from_fn(|i| {
3260 let v1 = lanes[2 * i] as i32;
3261 let v2 = lanes[2 * i + 1] as i32;
3262 v1.wrapping_add(v2)
3263 });
3264 resumable
3265 .stack
3266 .push_value(Value::V128(from_lanes(added_pairwise)))?;
3267 Ok(ControlFlow::Continue(()))
3268 }
3269}
3270define_instruction_fn! {
3271 i32x4_extadd_pairwise_i16x8_u,
3272 fuel_check = flat_fd(opcode::fd_extensions::I32X4_EXTADD_PAIRWISE_I16X8_U),
3273 |Args { resumable, .. }| {
3274 let data: [u8; 16] = resumable.stack.pop_value().try_into().unwrap_validated();
3275 let lanes: [u16; 8] = to_lanes(data);
3276 let added_pairwise: [u32; 4] = array::from_fn(|i| {
3277 let v1 = lanes[2 * i] as u32;
3278 let v2 = lanes[2 * i + 1] as u32;
3279 v1.wrapping_add(v2)
3280 });
3281 resumable
3282 .stack
3283 .push_value(Value::V128(from_lanes(added_pairwise)))?;
3284 Ok(ControlFlow::Continue(()))
3285 }
3286}