wasm/execution/interpreter_loop/
vector.rs

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
14// v128.const
15define_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
31// v128.vvunop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvunop>
32define_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
44// v128.vvbinop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvbinop>
45define_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
90// v128.vvternop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvternop>
91define_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
104// v128.vvtestop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vvtestop>
105define_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
116// i8x16.swizzle
117define_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
129// i8x16.shuffle
130define_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
153// shape.splat
154define_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
217// shape.extract_lane
218define_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
331// shape.replace_lane
332define_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
425// shape.vunop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vunop>
426define_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
726// shape.vbinop  <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vbinop>
727define_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
1516// txN.vrelop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vrelop>
1517define_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}
2058// vfrelop
2059define_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
2240// txN.vishiftop
2241define_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
2410// shape.vtestop <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vtestop>
2411define_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
2456// ishape.bitmask
2457define_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
2518// ishape.narrow_ishape_sx
2519define_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
2596// t_2xN.vcvtop_t_1xM_sx
2597define_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
2668// t_2xN.vcvtop_half_t_1xM_sx? <https://webassembly.github.io/spec/core/syntax/instructions.html#syntax-vcvtop>
2669define_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
2880// t_2xN.vcvtop_t_1xM_sx?_zero
2881define_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
2940// i32x4.dot_i16x8_s
2941define_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
2964// ishape.extmul_half_ishape_sx
2965define_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
3218// ishape.extadd_pairwise_ishape_sx
3219define_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}