pulley_interpreter/
interp.rs

1//! Interpretation of pulley bytecode.
2
3use crate::decode::*;
4use crate::encode::Encode;
5use crate::imms::*;
6use crate::profile::{ExecutingPc, ExecutingPcRef};
7use crate::regs::*;
8use alloc::string::ToString;
9use alloc::vec::Vec;
10use core::fmt;
11use core::mem;
12use core::ops::ControlFlow;
13use core::ops::{Index, IndexMut};
14use core::ptr::NonNull;
15use wasmtime_math::WasmFloat;
16mod debug;
17#[cfg(all(not(pulley_tail_calls), not(pulley_assume_llvm_makes_tail_calls)))]
18mod match_loop;
19#[cfg(any(pulley_tail_calls, pulley_assume_llvm_makes_tail_calls))]
20mod tail_loop;
21
22const DEFAULT_STACK_SIZE: usize = 1 << 20; // 1 MiB
23
24/// A virtual machine for interpreting Pulley bytecode.
25pub struct Vm {
26    state: MachineState,
27    executing_pc: ExecutingPc,
28}
29
30impl Default for Vm {
31    fn default() -> Self {
32        Vm::new()
33    }
34}
35
36impl Vm {
37    /// Create a new virtual machine with the default stack size.
38    pub fn new() -> Self {
39        Self::with_stack(DEFAULT_STACK_SIZE)
40    }
41
42    /// Create a new virtual machine with the given stack.
43    pub fn with_stack(stack_size: usize) -> Self {
44        Self {
45            state: MachineState::with_stack(stack_size),
46            executing_pc: ExecutingPc::default(),
47        }
48    }
49
50    /// Get a shared reference to this VM's machine state.
51    pub fn state(&self) -> &MachineState {
52        &self.state
53    }
54
55    /// Get an exclusive reference to this VM's machine state.
56    pub fn state_mut(&mut self) -> &mut MachineState {
57        &mut self.state
58    }
59
60    /// Call a bytecode function.
61    ///
62    /// The given `func` must point to the beginning of a valid Pulley bytecode
63    /// function.
64    ///
65    /// The given `args` must match the number and type of arguments that
66    /// function expects.
67    ///
68    /// The given `rets` must match the function's actual return types.
69    ///
70    /// Returns either the resulting values, or the PC at which a trap was
71    /// raised.
72    pub unsafe fn call<'a, T>(
73        &'a mut self,
74        func: NonNull<u8>,
75        args: &[Val],
76        rets: T,
77    ) -> DoneReason<impl Iterator<Item = Val> + use<'a, T>>
78    where
79        T: IntoIterator<Item = RegType> + 'a,
80    {
81        let lr = self.call_start(args);
82
83        match self.call_run(func) {
84            DoneReason::ReturnToHost(()) => DoneReason::ReturnToHost(self.call_end(lr, rets)),
85            DoneReason::Trap { pc, kind } => DoneReason::Trap { pc, kind },
86            DoneReason::CallIndirectHost { id, resume } => {
87                DoneReason::CallIndirectHost { id, resume }
88            }
89        }
90    }
91
92    /// Peforms the initial part of [`Vm::call`] in setting up the `args`
93    /// provided in registers according to Pulley's ABI.
94    ///
95    /// # Return
96    ///
97    /// Returns the old `lr` register value. The current `lr` value is replaced
98    /// with a sentinel that triggers a return to the host when returned-to.
99    ///
100    /// # Unsafety
101    ///
102    /// All the same unsafety as `call` and additiionally, you must
103    /// invoke `call_run` and then `call_end` after calling `call_start`.
104    /// If you don't want to wrangle these invocations, use `call` instead
105    /// of `call_{start,run,end}`.
106    pub unsafe fn call_start<'a>(&'a mut self, args: &[Val]) -> *mut u8 {
107        // NB: make sure this method stays in sync with
108        // `PulleyMachineDeps::compute_arg_locs`!
109
110        let mut x_args = (0..16).map(|x| XReg::new_unchecked(x));
111        let mut f_args = (0..16).map(|f| FReg::new_unchecked(f));
112        let mut v_args = (0..16).map(|v| VReg::new_unchecked(v));
113
114        for arg in args {
115            match arg {
116                Val::XReg(val) => match x_args.next() {
117                    Some(reg) => self.state[reg] = *val,
118                    None => todo!("stack slots"),
119                },
120                Val::FReg(val) => match f_args.next() {
121                    Some(reg) => self.state[reg] = *val,
122                    None => todo!("stack slots"),
123                },
124                Val::VReg(val) => match v_args.next() {
125                    Some(reg) => self.state[reg] = *val,
126                    None => todo!("stack slots"),
127                },
128            }
129        }
130
131        mem::replace(&mut self.state.lr, HOST_RETURN_ADDR)
132    }
133
134    /// Peforms the internal part of [`Vm::call`] where bytecode is actually
135    /// executed.
136    ///
137    /// # Unsafety
138    ///
139    /// In addition to all the invariants documented for `call`, you
140    /// may only invoke `call_run` after invoking `call_start` to
141    /// initialize this call's arguments.
142    pub unsafe fn call_run(&mut self, pc: NonNull<u8>) -> DoneReason<()> {
143        self.state.debug_assert_done_reason_none();
144        let interpreter = Interpreter {
145            state: &mut self.state,
146            pc: UnsafeBytecodeStream::new(pc),
147            executing_pc: self.executing_pc.as_ref(),
148        };
149        let done = interpreter.run();
150        self.state.done_decode(done)
151    }
152
153    /// Peforms the tail end of [`Vm::call`] by returning the values as
154    /// determined by `rets` according to Pulley's ABI.
155    ///
156    /// The `old_ret` value should have been provided from `call_start`
157    /// previously.
158    ///
159    /// # Unsafety
160    ///
161    /// In addition to the invariants documented for `call`, this may
162    /// only be called after `call_run`.
163    pub unsafe fn call_end<'a>(
164        &'a mut self,
165        old_ret: *mut u8,
166        rets: impl IntoIterator<Item = RegType> + 'a,
167    ) -> impl Iterator<Item = Val> + 'a {
168        self.state.lr = old_ret;
169        // NB: make sure this method stays in sync with
170        // `PulleyMachineDeps::compute_arg_locs`!
171
172        let mut x_rets = (0..15).map(|x| XReg::new_unchecked(x));
173        let mut f_rets = (0..16).map(|f| FReg::new_unchecked(f));
174        let mut v_rets = (0..16).map(|v| VReg::new_unchecked(v));
175
176        rets.into_iter().map(move |ty| match ty {
177            RegType::XReg => match x_rets.next() {
178                Some(reg) => Val::XReg(self.state[reg]),
179                None => todo!("stack slots"),
180            },
181            RegType::FReg => match f_rets.next() {
182                Some(reg) => Val::FReg(self.state[reg]),
183                None => todo!("stack slots"),
184            },
185            RegType::VReg => match v_rets.next() {
186                Some(reg) => Val::VReg(self.state[reg]),
187                None => todo!("stack slots"),
188            },
189        })
190    }
191
192    /// Returns the current `fp` register value.
193    pub fn fp(&self) -> *mut u8 {
194        self.state.fp
195    }
196
197    /// Returns the current `lr` register value.
198    pub fn lr(&self) -> *mut u8 {
199        self.state.lr
200    }
201
202    /// Sets the current `fp` register value.
203    pub unsafe fn set_fp(&mut self, fp: *mut u8) {
204        self.state.fp = fp;
205    }
206
207    /// Sets the current `lr` register value.
208    pub unsafe fn set_lr(&mut self, lr: *mut u8) {
209        self.state.lr = lr;
210    }
211
212    /// Gets a handle to the currently executing program counter for this
213    /// interpreter which can be read from other threads.
214    //
215    // Note that despite this field still existing with `not(feature =
216    // "profile")` it's hidden from the public API in that scenario as it has no
217    // methods anyway.
218    #[cfg(feature = "profile")]
219    pub fn executing_pc(&self) -> &ExecutingPc {
220        &self.executing_pc
221    }
222}
223
224impl Drop for Vm {
225    fn drop(&mut self) {
226        self.executing_pc.set_done();
227    }
228}
229
230/// The type of a register in the Pulley machine state.
231#[derive(Clone, Copy, Debug)]
232pub enum RegType {
233    /// An `x` register: integers.
234    XReg,
235
236    /// An `f` register: floats.
237    FReg,
238
239    /// A `v` register: vectors.
240    VReg,
241}
242
243/// A value that can be stored in a register.
244#[derive(Clone, Copy, Debug)]
245pub enum Val {
246    /// An `x` register value: integers.
247    XReg(XRegVal),
248
249    /// An `f` register value: floats.
250    FReg(FRegVal),
251
252    /// A `v` register value: vectors.
253    VReg(VRegVal),
254}
255
256impl fmt::LowerHex for Val {
257    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258        match self {
259            Val::XReg(v) => fmt::LowerHex::fmt(v, f),
260            Val::FReg(v) => fmt::LowerHex::fmt(v, f),
261            Val::VReg(v) => fmt::LowerHex::fmt(v, f),
262        }
263    }
264}
265
266impl From<XRegVal> for Val {
267    fn from(value: XRegVal) -> Self {
268        Val::XReg(value)
269    }
270}
271
272impl From<u64> for Val {
273    fn from(value: u64) -> Self {
274        XRegVal::new_u64(value).into()
275    }
276}
277
278impl From<u32> for Val {
279    fn from(value: u32) -> Self {
280        XRegVal::new_u32(value).into()
281    }
282}
283
284impl From<i64> for Val {
285    fn from(value: i64) -> Self {
286        XRegVal::new_i64(value).into()
287    }
288}
289
290impl From<i32> for Val {
291    fn from(value: i32) -> Self {
292        XRegVal::new_i32(value).into()
293    }
294}
295
296impl<T> From<*mut T> for Val {
297    fn from(value: *mut T) -> Self {
298        XRegVal::new_ptr(value).into()
299    }
300}
301
302impl From<FRegVal> for Val {
303    fn from(value: FRegVal) -> Self {
304        Val::FReg(value)
305    }
306}
307
308impl From<f64> for Val {
309    fn from(value: f64) -> Self {
310        FRegVal::new_f64(value).into()
311    }
312}
313
314impl From<f32> for Val {
315    fn from(value: f32) -> Self {
316        FRegVal::new_f32(value).into()
317    }
318}
319
320impl From<VRegVal> for Val {
321    fn from(value: VRegVal) -> Self {
322        Val::VReg(value)
323    }
324}
325
326/// An `x` register value: integers.
327#[derive(Copy, Clone)]
328pub struct XRegVal(XRegUnion);
329
330impl PartialEq for XRegVal {
331    fn eq(&self, other: &Self) -> bool {
332        self.get_u64() == other.get_u64()
333    }
334}
335
336impl Eq for XRegVal {}
337
338impl fmt::Debug for XRegVal {
339    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340        f.debug_struct("XRegVal")
341            .field("as_u64", &self.get_u64())
342            .finish()
343    }
344}
345
346impl fmt::LowerHex for XRegVal {
347    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
348        fmt::LowerHex::fmt(&self.get_u64(), f)
349    }
350}
351
352/// Contents of an "x" register, or a general-purpose register.
353///
354/// This is represented as a Rust `union` to make it easier to access typed
355/// views of this, notably the `ptr` field which enables preserving a bit of
356/// provenance for Rust for values stored as a pointer and read as a pointer.
357///
358/// Note that the actual in-memory representation of this value is handled
359/// carefully at this time. Pulley bytecode exposes the ability to store a
360/// 32-bit result into a register and then read the 64-bit contents of the
361/// register. This leaves us with the question of what to do with the upper bits
362/// of the register when the 32-bit result is generated. Possibilities for
363/// handling this are:
364///
365/// 1. Do nothing, just store the 32-bit value. The problem with this approach
366///    means that the "upper bits" are now endianness-dependent. That means that
367///    the state of the register is now platform-dependent.
368/// 2. Sign or zero-extend. This restores platform-independent behavior but
369///    requires an extra store on 32-bit platforms because they can probably
370///    only store 32-bits at a time.
371/// 3. Always store the values in this union as little-endian. This means that
372///    big-endian platforms have to do a byte-swap but otherwise it has
373///    platform-independent behavior.
374///
375/// This union chooses route (3) at this time where the values here are always
376/// stored in little-endian form (even the `ptr` field). That guarantees
377/// cross-platform behavior while also minimizing the amount of data stored on
378/// writes.
379///
380/// In the future we may wish to benchmark this and possibly change this.
381/// Technically Cranelift-generated bytecode should never rely on the upper bits
382/// of a register if it didn't previously write them so this in theory doesn't
383/// actually matter for Cranelift or wasm semantics. The only cost right now is
384/// to big-endian platforms though and it's not certain how crucial performance
385/// will be there.
386///
387/// One final note is that this notably contrasts with native CPUs where
388/// native ISAs like RISC-V specifically define the entire register on every
389/// instruction, even if only the low half contains a significant result. Pulley
390/// is unlikely to become out-of-order within the CPU itself as it's interpreted
391/// meaning that severing data-dependencies with previous operations is
392/// hypothesized to not be too important. If this is ever a problem though it
393/// could increase the likelihood we go for route (2) above instead (or maybe
394/// even (1)).
395#[derive(Copy, Clone)]
396union XRegUnion {
397    i32: i32,
398    u32: u32,
399    i64: i64,
400    u64: u64,
401
402    // Note that this is intentionally `usize` and not an actual pointer like
403    // `*mut u8`. The reason for this is that provenance is required in Rust for
404    // pointers but Cranelift has no pointer type and thus no concept of
405    // provenance. That means that at-rest it's not known whether the value has
406    // provenance or not and basically means that Pulley is required to use
407    // "permissive provenance" in Rust as opposed to strict provenance.
408    //
409    // That's more-or-less a long-winded way of saying that storage of a pointer
410    // in this value is done with `.expose_provenance()` and reading a pointer
411    // uses `with_exposed_provenance_mut(..)`.
412    ptr: usize,
413}
414
415impl Default for XRegVal {
416    fn default() -> Self {
417        Self(unsafe { mem::zeroed() })
418    }
419}
420
421#[allow(missing_docs, reason = "self-describing methods")]
422impl XRegVal {
423    pub fn new_i32(x: i32) -> Self {
424        let mut val = XRegVal::default();
425        val.set_i32(x);
426        val
427    }
428
429    pub fn new_u32(x: u32) -> Self {
430        let mut val = XRegVal::default();
431        val.set_u32(x);
432        val
433    }
434
435    pub fn new_i64(x: i64) -> Self {
436        let mut val = XRegVal::default();
437        val.set_i64(x);
438        val
439    }
440
441    pub fn new_u64(x: u64) -> Self {
442        let mut val = XRegVal::default();
443        val.set_u64(x);
444        val
445    }
446
447    pub fn new_ptr<T>(ptr: *mut T) -> Self {
448        let mut val = XRegVal::default();
449        val.set_ptr(ptr);
450        val
451    }
452
453    pub fn get_i32(&self) -> i32 {
454        let x = unsafe { self.0.i32 };
455        i32::from_le(x)
456    }
457
458    pub fn get_u32(&self) -> u32 {
459        let x = unsafe { self.0.u32 };
460        u32::from_le(x)
461    }
462
463    pub fn get_i64(&self) -> i64 {
464        let x = unsafe { self.0.i64 };
465        i64::from_le(x)
466    }
467
468    pub fn get_u64(&self) -> u64 {
469        let x = unsafe { self.0.u64 };
470        u64::from_le(x)
471    }
472
473    pub fn get_ptr<T>(&self) -> *mut T {
474        let ptr = unsafe { self.0.ptr };
475        let ptr = usize::from_le(ptr);
476        #[cfg(has_provenance_apis)]
477        return core::ptr::with_exposed_provenance_mut(ptr);
478        #[cfg(not(has_provenance_apis))]
479        return ptr as *mut T;
480    }
481
482    pub fn set_i32(&mut self, x: i32) {
483        self.0.i32 = x.to_le();
484    }
485
486    pub fn set_u32(&mut self, x: u32) {
487        self.0.u32 = x.to_le();
488    }
489
490    pub fn set_i64(&mut self, x: i64) {
491        self.0.i64 = x.to_le();
492    }
493
494    pub fn set_u64(&mut self, x: u64) {
495        self.0.u64 = x.to_le();
496    }
497
498    pub fn set_ptr<T>(&mut self, ptr: *mut T) {
499        #[cfg(has_provenance_apis)]
500        let ptr = ptr.expose_provenance();
501        #[cfg(not(has_provenance_apis))]
502        let ptr = ptr as usize;
503        self.0.ptr = ptr.to_le();
504    }
505}
506
507/// An `f` register value: floats.
508#[derive(Copy, Clone)]
509pub struct FRegVal(FRegUnion);
510
511impl fmt::Debug for FRegVal {
512    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513        f.debug_struct("FRegVal")
514            .field("as_f32", &self.get_f32())
515            .field("as_f64", &self.get_f64())
516            .finish()
517    }
518}
519
520impl fmt::LowerHex for FRegVal {
521    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522        fmt::LowerHex::fmt(&self.get_f64().to_bits(), f)
523    }
524}
525
526// NB: like `XRegUnion` values here are always little-endian, see the
527// documentation above for more details.
528#[derive(Copy, Clone)]
529union FRegUnion {
530    f32: u32,
531    f64: u64,
532}
533
534impl Default for FRegVal {
535    fn default() -> Self {
536        Self(unsafe { mem::zeroed() })
537    }
538}
539
540#[allow(missing_docs, reason = "self-describing methods")]
541impl FRegVal {
542    pub fn new_f32(f: f32) -> Self {
543        let mut val = Self::default();
544        val.set_f32(f);
545        val
546    }
547
548    pub fn new_f64(f: f64) -> Self {
549        let mut val = Self::default();
550        val.set_f64(f);
551        val
552    }
553
554    pub fn get_f32(&self) -> f32 {
555        let val = unsafe { self.0.f32 };
556        f32::from_le_bytes(val.to_ne_bytes())
557    }
558
559    pub fn get_f64(&self) -> f64 {
560        let val = unsafe { self.0.f64 };
561        f64::from_le_bytes(val.to_ne_bytes())
562    }
563
564    pub fn set_f32(&mut self, val: f32) {
565        self.0.f32 = u32::from_ne_bytes(val.to_le_bytes());
566    }
567
568    pub fn set_f64(&mut self, val: f64) {
569        self.0.f64 = u64::from_ne_bytes(val.to_le_bytes());
570    }
571}
572
573/// A `v` register value: vectors.
574#[derive(Copy, Clone)]
575pub struct VRegVal(VRegUnion);
576
577impl fmt::Debug for VRegVal {
578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579        f.debug_struct("VRegVal")
580            .field("as_u128", &unsafe { self.0.u128 })
581            .finish()
582    }
583}
584
585impl fmt::LowerHex for VRegVal {
586    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587        fmt::LowerHex::fmt(unsafe { &self.0.u128 }, f)
588    }
589}
590
591/// 128-bit vector registers.
592///
593/// This register is always stored in little-endian order and has different
594/// constraints than `XRegVal` and `FRegVal` above. Notably all fields of this
595/// union are the same width so all bits are always defined. Note that
596/// little-endian is required though so bitcasts between different shapes of
597/// vectors works. This union cannot be stored in big-endian.
598#[derive(Copy, Clone)]
599#[repr(align(16))]
600union VRegUnion {
601    u128: u128,
602    i8x16: [i8; 16],
603    i16x8: [i16; 8],
604    i32x4: [i32; 4],
605    i64x2: [i64; 2],
606    u8x16: [u8; 16],
607    u16x8: [u16; 8],
608    u32x4: [u32; 4],
609    u64x2: [u64; 2],
610    // Note that these are `u32` and `u64`, not f32/f64. That's only because
611    // f32/f64 don't have `.to_le()` and `::from_le()` so need to go through the
612    // bits anyway.
613    f32x4: [u32; 4],
614    f64x2: [u64; 2],
615}
616
617impl Default for VRegVal {
618    fn default() -> Self {
619        Self(unsafe { mem::zeroed() })
620    }
621}
622
623#[allow(missing_docs, reason = "self-describing methods")]
624impl VRegVal {
625    pub fn new_u128(i: u128) -> Self {
626        let mut val = Self::default();
627        val.set_u128(i);
628        val
629    }
630
631    pub fn get_u128(&self) -> u128 {
632        let val = unsafe { self.0.u128 };
633        u128::from_le(val)
634    }
635
636    pub fn set_u128(&mut self, val: u128) {
637        self.0.u128 = val.to_le();
638    }
639
640    fn get_i8x16(&self) -> [i8; 16] {
641        let val = unsafe { self.0.i8x16 };
642        val.map(|e| i8::from_le(e))
643    }
644
645    fn set_i8x16(&mut self, val: [i8; 16]) {
646        self.0.i8x16 = val.map(|e| e.to_le());
647    }
648
649    fn get_u8x16(&self) -> [u8; 16] {
650        let val = unsafe { self.0.u8x16 };
651        val.map(|e| u8::from_le(e))
652    }
653
654    fn set_u8x16(&mut self, val: [u8; 16]) {
655        self.0.u8x16 = val.map(|e| e.to_le());
656    }
657
658    fn get_i16x8(&self) -> [i16; 8] {
659        let val = unsafe { self.0.i16x8 };
660        val.map(|e| i16::from_le(e))
661    }
662
663    fn set_i16x8(&mut self, val: [i16; 8]) {
664        self.0.i16x8 = val.map(|e| e.to_le());
665    }
666
667    fn get_u16x8(&self) -> [u16; 8] {
668        let val = unsafe { self.0.u16x8 };
669        val.map(|e| u16::from_le(e))
670    }
671
672    fn set_u16x8(&mut self, val: [u16; 8]) {
673        self.0.u16x8 = val.map(|e| e.to_le());
674    }
675
676    fn get_i32x4(&self) -> [i32; 4] {
677        let val = unsafe { self.0.i32x4 };
678        val.map(|e| i32::from_le(e))
679    }
680
681    fn set_i32x4(&mut self, val: [i32; 4]) {
682        self.0.i32x4 = val.map(|e| e.to_le());
683    }
684
685    fn get_u32x4(&self) -> [u32; 4] {
686        let val = unsafe { self.0.u32x4 };
687        val.map(|e| u32::from_le(e))
688    }
689
690    fn set_u32x4(&mut self, val: [u32; 4]) {
691        self.0.u32x4 = val.map(|e| e.to_le());
692    }
693
694    fn get_i64x2(&self) -> [i64; 2] {
695        let val = unsafe { self.0.i64x2 };
696        val.map(|e| i64::from_le(e))
697    }
698
699    fn set_i64x2(&mut self, val: [i64; 2]) {
700        self.0.i64x2 = val.map(|e| e.to_le());
701    }
702
703    fn get_u64x2(&self) -> [u64; 2] {
704        let val = unsafe { self.0.u64x2 };
705        val.map(|e| u64::from_le(e))
706    }
707
708    fn set_u64x2(&mut self, val: [u64; 2]) {
709        self.0.u64x2 = val.map(|e| e.to_le());
710    }
711
712    fn get_f64x2(&self) -> [f64; 2] {
713        let val = unsafe { self.0.f64x2 };
714        val.map(|e| f64::from_bits(u64::from_le(e)))
715    }
716
717    fn set_f64x2(&mut self, val: [f64; 2]) {
718        self.0.f64x2 = val.map(|e| e.to_bits().to_le());
719    }
720
721    fn get_f32x4(&self) -> [f32; 4] {
722        let val = unsafe { self.0.f32x4 };
723        val.map(|e| f32::from_bits(u32::from_le(e)))
724    }
725
726    fn set_f32x4(&mut self, val: [f32; 4]) {
727        self.0.f32x4 = val.map(|e| e.to_bits().to_le());
728    }
729}
730
731/// The machine state for a Pulley virtual machine: the various registers and
732/// stack.
733pub struct MachineState {
734    x_regs: [XRegVal; XReg::RANGE.end as usize],
735    f_regs: [FRegVal; FReg::RANGE.end as usize],
736    v_regs: [VRegVal; VReg::RANGE.end as usize],
737    fp: *mut u8,
738    lr: *mut u8,
739    stack: Stack,
740    done_reason: Option<DoneReason<()>>,
741}
742
743unsafe impl Send for MachineState {}
744unsafe impl Sync for MachineState {}
745
746/// Helper structure to store the state of the Pulley stack.
747///
748/// The Pulley stack notably needs to be a 16-byte aligned allocation on the
749/// host to ensure that addresses handed out are indeed 16-byte aligned. This is
750/// done with a custom `Vec<T>` internally where `T` has size and align of 16.
751/// This is manually done with a helper `Align16` type below.
752struct Stack {
753    storage: Vec<Align16>,
754}
755
756/// Helper type used with `Stack` above.
757#[derive(Copy, Clone)]
758#[repr(align(16))]
759struct Align16 {
760    // Just here to give the structure a size of 16. The alignment is always 16
761    // regardless of what the host platform's alignment of u128 is.
762    _unused: u128,
763}
764
765impl Stack {
766    /// Creates a new stack which will have a byte size of at least `size`.
767    ///
768    /// The allocated stack might be slightly larger due to rounding necessary.
769    fn new(size: usize) -> Stack {
770        Stack {
771            // Round up `size` to the nearest multiple of 16. Note that the
772            // stack is also allocated here but not initialized, and that's
773            // intentional as pulley bytecode should always initialize the stack
774            // before use.
775            storage: Vec::with_capacity((size + 15) / 16),
776        }
777    }
778
779    /// Returns a pointer to the top of the stack (the highest address).
780    ///
781    /// Note that the returned pointer has provenance for the entire stack
782    /// allocation, however, not just the top.
783    fn top(&mut self) -> *mut u8 {
784        let len = self.len();
785        unsafe { self.base().add(len) }
786    }
787
788    /// Returns a pointer to the base of the stack (the lowest address).
789    ///
790    /// Note that the returned pointer has provenance for the entire stack
791    /// allocation, however, not just the top.
792    fn base(&mut self) -> *mut u8 {
793        self.storage.as_mut_ptr().cast::<u8>()
794    }
795
796    /// Returns the length, in bytes, of this stack allocation.
797    fn len(&self) -> usize {
798        self.storage.capacity() * mem::size_of::<Align16>()
799    }
800}
801
802impl fmt::Debug for MachineState {
803    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
804        let MachineState {
805            x_regs,
806            f_regs,
807            v_regs,
808            stack: _,
809            done_reason: _,
810            fp: _,
811            lr: _,
812        } = self;
813
814        struct RegMap<'a, R>(&'a [R], fn(u8) -> alloc::string::String);
815
816        impl<R: fmt::Debug> fmt::Debug for RegMap<'_, R> {
817            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
818                let mut f = f.debug_map();
819                for (i, r) in self.0.iter().enumerate() {
820                    f.entry(&(self.1)(i as u8), r);
821                }
822                f.finish()
823            }
824        }
825
826        f.debug_struct("MachineState")
827            .field(
828                "x_regs",
829                &RegMap(x_regs, |i| XReg::new(i).unwrap().to_string()),
830            )
831            .field(
832                "f_regs",
833                &RegMap(f_regs, |i| FReg::new(i).unwrap().to_string()),
834            )
835            .field(
836                "v_regs",
837                &RegMap(v_regs, |i| VReg::new(i).unwrap().to_string()),
838            )
839            .finish_non_exhaustive()
840    }
841}
842
843macro_rules! index_reg {
844    ($reg_ty:ty,$value_ty:ty,$field:ident) => {
845        impl Index<$reg_ty> for Vm {
846            type Output = $value_ty;
847
848            fn index(&self, reg: $reg_ty) -> &Self::Output {
849                &self.state[reg]
850            }
851        }
852
853        impl IndexMut<$reg_ty> for Vm {
854            fn index_mut(&mut self, reg: $reg_ty) -> &mut Self::Output {
855                &mut self.state[reg]
856            }
857        }
858
859        impl Index<$reg_ty> for MachineState {
860            type Output = $value_ty;
861
862            fn index(&self, reg: $reg_ty) -> &Self::Output {
863                &self.$field[reg.index()]
864            }
865        }
866
867        impl IndexMut<$reg_ty> for MachineState {
868            fn index_mut(&mut self, reg: $reg_ty) -> &mut Self::Output {
869                &mut self.$field[reg.index()]
870            }
871        }
872    };
873}
874
875index_reg!(XReg, XRegVal, x_regs);
876index_reg!(FReg, FRegVal, f_regs);
877index_reg!(VReg, VRegVal, v_regs);
878
879/// Sentinel return address that signals the end of the call stack.
880const HOST_RETURN_ADDR: *mut u8 = usize::MAX as *mut u8;
881
882impl MachineState {
883    fn with_stack(stack_size: usize) -> Self {
884        let mut state = Self {
885            x_regs: [Default::default(); XReg::RANGE.end as usize],
886            f_regs: Default::default(),
887            v_regs: Default::default(),
888            stack: Stack::new(stack_size),
889            done_reason: None,
890            fp: HOST_RETURN_ADDR,
891            lr: HOST_RETURN_ADDR,
892        };
893
894        let sp = state.stack.top();
895        state[XReg::sp] = XRegVal::new_ptr(sp);
896
897        state
898    }
899}
900
901/// Inner private module to prevent creation of the `Done` structure outside of
902/// this module.
903mod done {
904    use super::{Encode, Interpreter, MachineState};
905    use core::ops::ControlFlow;
906    use core::ptr::NonNull;
907
908    /// Zero-sized sentinel indicating that pulley execution has halted.
909    ///
910    /// The reason for halting is stored in `MachineState`.
911    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
912    pub struct Done {
913        _priv: (),
914    }
915
916    /// Reason that the pulley interpreter has ceased execution.
917    pub enum DoneReason<T> {
918        /// A trap happened at this bytecode instruction.
919        Trap {
920            /// Which instruction is raising this trap.
921            pc: NonNull<u8>,
922            /// The kind of trap being raised, if known.
923            kind: Option<TrapKind>,
924        },
925        /// The `call_indirect_host` instruction was executed.
926        CallIndirectHost {
927            /// The payload of `call_indirect_host`.
928            id: u8,
929            /// Where to resume execution after the host has finished.
930            resume: NonNull<u8>,
931        },
932        /// Pulley has finished and the provided value is being returned.
933        ReturnToHost(T),
934    }
935
936    /// Stored within `DoneReason::Trap`.
937    #[allow(missing_docs, reason = "self-describing variants")]
938    pub enum TrapKind {
939        DivideByZero,
940        IntegerOverflow,
941        BadConversionToInteger,
942    }
943
944    impl MachineState {
945        pub(super) fn debug_assert_done_reason_none(&mut self) {
946            debug_assert!(self.done_reason.is_none());
947        }
948
949        pub(super) fn done_decode(&mut self, Done { _priv }: Done) -> DoneReason<()> {
950            self.done_reason.take().unwrap()
951        }
952    }
953
954    impl Interpreter<'_> {
955        /// Finishes execution by recording `DoneReason::Trap`.
956        ///
957        /// This method takes an `I` generic parameter indicating which
958        /// instruction is executing this function and generating a trap. That's
959        /// used to go backwards from the current `pc` which is just beyond the
960        /// instruction to point to the instruction itself in the trap metadata
961        /// returned from the interpreter.
962        pub fn done_trap<I: Encode>(&mut self) -> ControlFlow<Done> {
963            self.done_trap_kind::<I>(None)
964        }
965
966        /// Same as `done_trap` but with an explicit `TrapKind`.
967        pub fn done_trap_kind<I: Encode>(&mut self, kind: Option<TrapKind>) -> ControlFlow<Done> {
968            let pc = self.current_pc::<I>();
969            self.state.done_reason = Some(DoneReason::Trap { pc, kind });
970            ControlFlow::Break(Done { _priv: () })
971        }
972
973        /// Finishes execution by recording `DoneReason::CallIndirectHost`.
974        pub fn done_call_indirect_host(&mut self, id: u8) -> ControlFlow<Done> {
975            self.state.done_reason = Some(DoneReason::CallIndirectHost {
976                id,
977                resume: self.pc.as_ptr(),
978            });
979            ControlFlow::Break(Done { _priv: () })
980        }
981
982        /// Finishes execution by recording `DoneReason::ReturnToHost`.
983        pub fn done_return_to_host(&mut self) -> ControlFlow<Done> {
984            self.state.done_reason = Some(DoneReason::ReturnToHost(()));
985            ControlFlow::Break(Done { _priv: () })
986        }
987    }
988}
989
990use done::Done;
991pub use done::{DoneReason, TrapKind};
992
993struct Interpreter<'a> {
994    state: &'a mut MachineState,
995    pc: UnsafeBytecodeStream,
996    executing_pc: ExecutingPcRef<'a>,
997}
998
999impl Interpreter<'_> {
1000    /// Performs a relative jump of `offset` bytes from the current instruction.
1001    ///
1002    /// This will jump from the start of the current instruction, identified by
1003    /// `I`, `offset` bytes away. Note that the `self.pc` at the start of this
1004    /// function actually points to the instruction after this one so `I` is
1005    /// necessary to go back to ourselves after which we then go `offset` away.
1006    #[inline]
1007    fn pc_rel_jump<I: Encode>(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1008        let offset = isize::try_from(i32::from(offset)).unwrap();
1009        let my_pc = self.current_pc::<I>();
1010        self.pc = unsafe { UnsafeBytecodeStream::new(my_pc.offset(offset)) };
1011        ControlFlow::Continue(())
1012    }
1013
1014    /// Returns the PC of the current instruction where `I` is the static type
1015    /// representing the current instruction.
1016    fn current_pc<I: Encode>(&self) -> NonNull<u8> {
1017        unsafe { self.pc.offset(-isize::from(I::WIDTH)).as_ptr() }
1018    }
1019
1020    /// `sp -= size_of::<T>(); *sp = val;`
1021    ///
1022    /// Note that `I` is the instruction which is pushing data to use if a trap
1023    /// is generated.
1024    #[must_use]
1025    fn push<I: Encode, T>(&mut self, val: T) -> ControlFlow<Done> {
1026        let new_sp = self.state[XReg::sp].get_ptr::<T>().wrapping_sub(1);
1027        self.set_sp::<I>(new_sp.cast())?;
1028        unsafe {
1029            new_sp.write_unaligned(val);
1030        }
1031        ControlFlow::Continue(())
1032    }
1033
1034    /// `ret = *sp; sp -= size_of::<T>()`
1035    fn pop<T>(&mut self) -> T {
1036        let sp = self.state[XReg::sp].get_ptr::<T>();
1037        let val = unsafe { sp.read_unaligned() };
1038        self.set_sp_unchecked(sp.wrapping_add(1));
1039        val
1040    }
1041
1042    /// Sets the stack pointer to the `sp` provided.
1043    ///
1044    /// Returns a trap if this would result in stack overflow, or if `sp` is
1045    /// beneath the base pointer of `self.state.stack`.
1046    ///
1047    /// The `I` parameter here is the instruction that is setting the stack
1048    /// pointer and is used to calculate this instruction's own `pc` if this
1049    /// instruction traps.
1050    #[must_use]
1051    fn set_sp<I: Encode>(&mut self, sp: *mut u8) -> ControlFlow<Done> {
1052        let sp_raw = sp as usize;
1053        let base_raw = self.state.stack.base() as usize;
1054        if sp_raw < base_raw {
1055            return self.done_trap::<I>();
1056        }
1057        self.set_sp_unchecked(sp);
1058        ControlFlow::Continue(())
1059    }
1060
1061    /// Same as `set_sp` but does not check to see if `sp` is in-bounds. Should
1062    /// only be used with stack increment operations such as `pop`.
1063    fn set_sp_unchecked<T>(&mut self, sp: *mut T) {
1064        if cfg!(debug_assertions) {
1065            let sp_raw = sp as usize;
1066            let base = self.state.stack.base() as usize;
1067            let end = base + self.state.stack.len();
1068            assert!(base <= sp_raw && sp_raw <= end);
1069        }
1070        self.state[XReg::sp].set_ptr(sp);
1071    }
1072
1073    /// Calculates the "g32" address given the inputs to the addressing mode.
1074    fn g32_addr<T>(&self, base: XReg, addr: XReg, offset: u8) -> *mut T {
1075        let addr = (self.state[base].get_ptr::<T>() as usize)
1076            .wrapping_add(self.state[addr].get_u32() as usize)
1077            .wrapping_add(usize::from(offset));
1078        addr as *mut T
1079    }
1080
1081    unsafe fn load<T>(&self, ptr: XReg, offset: i32) -> T {
1082        unsafe {
1083            self.state[ptr]
1084                .get_ptr::<T>()
1085                .byte_offset(offset as isize)
1086                .read_unaligned()
1087        }
1088    }
1089
1090    /// The name "g32" here means that the guest pointer, the wasm address, is
1091    /// always a 32-bit value. Arithmetic is done at the size of the
1092    /// host-pointer-width.
1093    unsafe fn load_g32<T>(&self, base: XReg, addr: XReg, offset: u8) -> T {
1094        unsafe { self.g32_addr::<T>(base, addr, offset).read_unaligned() }
1095    }
1096
1097    unsafe fn store<T>(&self, ptr: XReg, offset: i32, val: T) {
1098        self.state[ptr]
1099            .get_ptr::<T>()
1100            .byte_offset(offset as isize)
1101            .write_unaligned(val)
1102    }
1103
1104    /// Same as `load_g32` but for stores
1105    unsafe fn store_g32<T>(&self, base: XReg, addr: XReg, offset: u8, val: T) {
1106        unsafe {
1107            self.g32_addr::<T>(base, addr, offset).write_unaligned(val);
1108        }
1109    }
1110
1111    fn check_xnn_from_fnn<I: Encode>(&mut self, val: f64, lo: f64, hi: f64) -> ControlFlow<Done> {
1112        if val != val {
1113            return self.done_trap_kind::<I>(Some(TrapKind::BadConversionToInteger));
1114        }
1115        let val = val.wasm_trunc();
1116        if val <= lo || val >= hi {
1117            return self.done_trap_kind::<I>(Some(TrapKind::IntegerOverflow));
1118        }
1119        ControlFlow::Continue(())
1120    }
1121
1122    fn get_i128(&self, lo: XReg, hi: XReg) -> i128 {
1123        let lo = self.state[lo].get_u64();
1124        let hi = self.state[hi].get_i64();
1125        i128::from(lo) | (i128::from(hi) << 64)
1126    }
1127
1128    fn set_i128(&mut self, lo: XReg, hi: XReg, val: i128) {
1129        self.state[lo].set_u64(val as u64);
1130        self.state[hi].set_u64((val >> 64) as u64);
1131    }
1132
1133    fn record_executing_pc_for_profiling(&mut self) {
1134        // Note that this is a no-op if `feature = "profile"` is disabled.
1135        self.executing_pc.record(self.pc.as_ptr().as_ptr() as usize);
1136    }
1137}
1138
1139#[test]
1140fn simple_push_pop() {
1141    let mut state = MachineState::with_stack(16);
1142    let pc = ExecutingPc::default();
1143    unsafe {
1144        let mut bytecode = [0; 10];
1145        let mut i = Interpreter {
1146            state: &mut state,
1147            // this isn't actually read so just manufacture a dummy one
1148            pc: UnsafeBytecodeStream::new(NonNull::new(bytecode.as_mut_ptr().offset(4)).unwrap()),
1149            executing_pc: pc.as_ref(),
1150        };
1151        assert!(i.push::<crate::Ret, _>(0_i32).is_continue());
1152        assert_eq!(i.pop::<i32>(), 0_i32);
1153        assert!(i.push::<crate::Ret, _>(1_i32).is_continue());
1154        assert!(i.push::<crate::Ret, _>(2_i32).is_continue());
1155        assert!(i.push::<crate::Ret, _>(3_i32).is_continue());
1156        assert!(i.push::<crate::Ret, _>(4_i32).is_continue());
1157        assert!(i.push::<crate::Ret, _>(5_i32).is_break());
1158        assert!(i.push::<crate::Ret, _>(6_i32).is_break());
1159        assert_eq!(i.pop::<i32>(), 4_i32);
1160        assert_eq!(i.pop::<i32>(), 3_i32);
1161        assert_eq!(i.pop::<i32>(), 2_i32);
1162        assert_eq!(i.pop::<i32>(), 1_i32);
1163    }
1164}
1165
1166macro_rules! br_if_imm {
1167    ($(
1168        fn $snake:ident(&mut self, a: XReg, b: $imm:ident, offset: PcRelOffset)
1169            = $camel:ident / $op:tt / $get:ident;
1170    )*) => {$(
1171        fn $snake(&mut self, a: XReg, b: $imm, offset: PcRelOffset) -> ControlFlow<Done> {
1172            let a = self.state[a].$get();
1173            if a $op b.into() {
1174                self.pc_rel_jump::<crate::$camel>(offset)
1175            } else {
1176                ControlFlow::Continue(())
1177            }
1178        }
1179    )*};
1180}
1181
1182impl OpVisitor for Interpreter<'_> {
1183    type BytecodeStream = UnsafeBytecodeStream;
1184    type Return = ControlFlow<Done>;
1185
1186    fn bytecode(&mut self) -> &mut UnsafeBytecodeStream {
1187        &mut self.pc
1188    }
1189
1190    fn ret(&mut self) -> ControlFlow<Done> {
1191        let lr = self.state.lr;
1192        if lr == HOST_RETURN_ADDR {
1193            self.done_return_to_host()
1194        } else {
1195            self.pc = unsafe { UnsafeBytecodeStream::new(NonNull::new_unchecked(lr)) };
1196            ControlFlow::Continue(())
1197        }
1198    }
1199
1200    fn call(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1201        let return_addr = self.pc.as_ptr();
1202        self.state.lr = return_addr.as_ptr();
1203        self.pc_rel_jump::<crate::Call>(offset);
1204        ControlFlow::Continue(())
1205    }
1206
1207    fn call1(&mut self, arg1: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1208        let return_addr = self.pc.as_ptr();
1209        self.state.lr = return_addr.as_ptr();
1210        self.state[XReg::x0] = self.state[arg1];
1211        self.pc_rel_jump::<crate::Call1>(offset);
1212        ControlFlow::Continue(())
1213    }
1214
1215    fn call2(&mut self, arg1: XReg, arg2: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1216        let return_addr = self.pc.as_ptr();
1217        self.state.lr = return_addr.as_ptr();
1218        let (x0, x1) = (self.state[arg1], self.state[arg2]);
1219        self.state[XReg::x0] = x0;
1220        self.state[XReg::x1] = x1;
1221        self.pc_rel_jump::<crate::Call2>(offset);
1222        ControlFlow::Continue(())
1223    }
1224
1225    fn call3(
1226        &mut self,
1227        arg1: XReg,
1228        arg2: XReg,
1229        arg3: XReg,
1230        offset: PcRelOffset,
1231    ) -> ControlFlow<Done> {
1232        let return_addr = self.pc.as_ptr();
1233        self.state.lr = return_addr.as_ptr();
1234        let (x0, x1, x2) = (self.state[arg1], self.state[arg2], self.state[arg3]);
1235        self.state[XReg::x0] = x0;
1236        self.state[XReg::x1] = x1;
1237        self.state[XReg::x2] = x2;
1238        self.pc_rel_jump::<crate::Call3>(offset);
1239        ControlFlow::Continue(())
1240    }
1241
1242    fn call4(
1243        &mut self,
1244        arg1: XReg,
1245        arg2: XReg,
1246        arg3: XReg,
1247        arg4: XReg,
1248        offset: PcRelOffset,
1249    ) -> ControlFlow<Done> {
1250        let return_addr = self.pc.as_ptr();
1251        self.state.lr = return_addr.as_ptr();
1252        let (x0, x1, x2, x3) = (
1253            self.state[arg1],
1254            self.state[arg2],
1255            self.state[arg3],
1256            self.state[arg4],
1257        );
1258        self.state[XReg::x0] = x0;
1259        self.state[XReg::x1] = x1;
1260        self.state[XReg::x2] = x2;
1261        self.state[XReg::x3] = x3;
1262        self.pc_rel_jump::<crate::Call4>(offset);
1263        ControlFlow::Continue(())
1264    }
1265
1266    fn call_indirect(&mut self, dst: XReg) -> ControlFlow<Done> {
1267        let return_addr = self.pc.as_ptr();
1268        self.state.lr = return_addr.as_ptr();
1269        // SAFETY: part of the unsafe contract of the interpreter is only valid
1270        // bytecode is interpreted, so the jump destination is part of the validity
1271        // of the bytecode itself.
1272        unsafe {
1273            self.pc = UnsafeBytecodeStream::new(NonNull::new_unchecked(self.state[dst].get_ptr()));
1274        }
1275        ControlFlow::Continue(())
1276    }
1277
1278    fn jump(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1279        self.pc_rel_jump::<crate::Jump>(offset);
1280        ControlFlow::Continue(())
1281    }
1282
1283    fn xjump(&mut self, reg: XReg) -> ControlFlow<Done> {
1284        unsafe {
1285            self.pc = UnsafeBytecodeStream::new(NonNull::new_unchecked(self.state[reg].get_ptr()));
1286        }
1287        ControlFlow::Continue(())
1288    }
1289
1290    fn br_if32(&mut self, cond: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1291        let cond = self.state[cond].get_u32();
1292        if cond != 0 {
1293            self.pc_rel_jump::<crate::BrIf>(offset)
1294        } else {
1295            ControlFlow::Continue(())
1296        }
1297    }
1298
1299    fn br_if_not32(&mut self, cond: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1300        let cond = self.state[cond].get_u32();
1301        if cond == 0 {
1302            self.pc_rel_jump::<crate::BrIfNot>(offset)
1303        } else {
1304            ControlFlow::Continue(())
1305        }
1306    }
1307
1308    fn br_if_xeq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1309        let a = self.state[a].get_u32();
1310        let b = self.state[b].get_u32();
1311        if a == b {
1312            self.pc_rel_jump::<crate::BrIfXeq32>(offset)
1313        } else {
1314            ControlFlow::Continue(())
1315        }
1316    }
1317
1318    fn br_if_xneq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1319        let a = self.state[a].get_u32();
1320        let b = self.state[b].get_u32();
1321        if a != b {
1322            self.pc_rel_jump::<crate::BrIfXneq32>(offset)
1323        } else {
1324            ControlFlow::Continue(())
1325        }
1326    }
1327
1328    fn br_if_xslt32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1329        let a = self.state[a].get_i32();
1330        let b = self.state[b].get_i32();
1331        if a < b {
1332            self.pc_rel_jump::<crate::BrIfXslt32>(offset)
1333        } else {
1334            ControlFlow::Continue(())
1335        }
1336    }
1337
1338    fn br_if_xslteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1339        let a = self.state[a].get_i32();
1340        let b = self.state[b].get_i32();
1341        if a <= b {
1342            self.pc_rel_jump::<crate::BrIfXslteq32>(offset)
1343        } else {
1344            ControlFlow::Continue(())
1345        }
1346    }
1347
1348    fn br_if_xult32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1349        let a = self.state[a].get_u32();
1350        let b = self.state[b].get_u32();
1351        if a < b {
1352            self.pc_rel_jump::<crate::BrIfXult32>(offset)
1353        } else {
1354            ControlFlow::Continue(())
1355        }
1356    }
1357
1358    fn br_if_xulteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1359        let a = self.state[a].get_u32();
1360        let b = self.state[b].get_u32();
1361        if a <= b {
1362            self.pc_rel_jump::<crate::BrIfXulteq32>(offset)
1363        } else {
1364            ControlFlow::Continue(())
1365        }
1366    }
1367
1368    fn br_if_xeq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1369        let a = self.state[a].get_u64();
1370        let b = self.state[b].get_u64();
1371        if a == b {
1372            self.pc_rel_jump::<crate::BrIfXeq64>(offset)
1373        } else {
1374            ControlFlow::Continue(())
1375        }
1376    }
1377
1378    fn br_if_xneq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1379        let a = self.state[a].get_u64();
1380        let b = self.state[b].get_u64();
1381        if a != b {
1382            self.pc_rel_jump::<crate::BrIfXneq64>(offset)
1383        } else {
1384            ControlFlow::Continue(())
1385        }
1386    }
1387
1388    fn br_if_xslt64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1389        let a = self.state[a].get_i64();
1390        let b = self.state[b].get_i64();
1391        if a < b {
1392            self.pc_rel_jump::<crate::BrIfXslt64>(offset)
1393        } else {
1394            ControlFlow::Continue(())
1395        }
1396    }
1397
1398    fn br_if_xslteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1399        let a = self.state[a].get_i64();
1400        let b = self.state[b].get_i64();
1401        if a <= b {
1402            self.pc_rel_jump::<crate::BrIfXslteq64>(offset)
1403        } else {
1404            ControlFlow::Continue(())
1405        }
1406    }
1407
1408    fn br_if_xult64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1409        let a = self.state[a].get_u64();
1410        let b = self.state[b].get_u64();
1411        if a < b {
1412            self.pc_rel_jump::<crate::BrIfXult64>(offset)
1413        } else {
1414            ControlFlow::Continue(())
1415        }
1416    }
1417
1418    fn br_if_xulteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1419        let a = self.state[a].get_u64();
1420        let b = self.state[b].get_u64();
1421        if a <= b {
1422            self.pc_rel_jump::<crate::BrIfXulteq64>(offset)
1423        } else {
1424            ControlFlow::Continue(())
1425        }
1426    }
1427
1428    br_if_imm! {
1429        fn br_if_xeq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1430            = BrIfXeq32I8 / == / get_i32;
1431        fn br_if_xeq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1432            = BrIfXeq32I32 / == / get_i32;
1433        fn br_if_xneq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1434            = BrIfXneq32I8 / != / get_i32;
1435        fn br_if_xneq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1436            = BrIfXneq32I32 / != / get_i32;
1437
1438        fn br_if_xslt32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1439            = BrIfXslt32I8 / < / get_i32;
1440        fn br_if_xslt32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1441            = BrIfXslt32I32 / < / get_i32;
1442        fn br_if_xsgt32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1443            = BrIfXsgt32I8 / > / get_i32;
1444        fn br_if_xsgt32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1445            = BrIfXsgt32I32 / > / get_i32;
1446        fn br_if_xslteq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1447            = BrIfXslteq32I8 / <= / get_i32;
1448        fn br_if_xslteq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1449            = BrIfXslteq32I32 / <= / get_i32;
1450        fn br_if_xsgteq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1451            = BrIfXsgteq32I8 / >= / get_i32;
1452        fn br_if_xsgteq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1453            = BrIfXsgteq32I32 / >= / get_i32;
1454
1455        fn br_if_xult32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1456            = BrIfXult32U8 / < / get_u32;
1457        fn br_if_xult32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1458            = BrIfXult32U32 / < / get_u32;
1459        fn br_if_xugt32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1460            = BrIfXugt32U8 / > / get_u32;
1461        fn br_if_xugt32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1462            = BrIfXugt32U32 / > / get_u32;
1463        fn br_if_xulteq32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1464            = BrIfXulteq32U8 / <= / get_u32;
1465        fn br_if_xulteq32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1466            = BrIfXulteq32U32 / <= / get_u32;
1467        fn br_if_xugteq32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1468            = BrIfXugteq32U8 / >= / get_u32;
1469        fn br_if_xugteq32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1470            = BrIfXugteq32U32 / >= / get_u32;
1471
1472        fn br_if_xeq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1473            = BrIfXeq64I8 / == / get_i64;
1474        fn br_if_xeq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1475            = BrIfXeq64I32 / == / get_i64;
1476        fn br_if_xneq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1477            = BrIfXneq64I8 / != / get_i64;
1478        fn br_if_xneq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1479            = BrIfXneq64I32 / != / get_i64;
1480
1481        fn br_if_xslt64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1482            = BrIfXslt64I8 / < / get_i64;
1483        fn br_if_xslt64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1484            = BrIfXslt64I32 / < / get_i64;
1485        fn br_if_xsgt64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1486            = BrIfXsgt64I8 / > / get_i64;
1487        fn br_if_xsgt64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1488            = BrIfXsgt64I32 / > / get_i64;
1489        fn br_if_xslteq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1490            = BrIfXslteq64I8 / <= / get_i64;
1491        fn br_if_xslteq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1492            = BrIfXslteq64I32 / <= / get_i64;
1493        fn br_if_xsgteq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1494            = BrIfXsgteq64I8 / >= / get_i64;
1495        fn br_if_xsgteq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1496            = BrIfXsgteq64I32 / >= / get_i64;
1497
1498        fn br_if_xult64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1499            = BrIfXult64U8 / < / get_u64;
1500        fn br_if_xult64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1501            = BrIfXult64U32 / < / get_u64;
1502        fn br_if_xugt64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1503            = BrIfXugt64U8 / > / get_u64;
1504        fn br_if_xugt64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1505            = BrIfXugt64U32 / > / get_u64;
1506        fn br_if_xulteq64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1507            = BrIfXulteq64U8 / <= / get_u64;
1508        fn br_if_xulteq64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1509            = BrIfXulteq64U32 / <= / get_u64;
1510        fn br_if_xugteq64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1511            = BrIfXugteq64U8 / >= / get_u64;
1512        fn br_if_xugteq64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1513            = BrIfXugteq64U32 / >= / get_u64;
1514    }
1515
1516    fn xmov(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1517        let val = self.state[src];
1518        self.state[dst] = val;
1519        ControlFlow::Continue(())
1520    }
1521
1522    fn xconst8(&mut self, dst: XReg, imm: i8) -> ControlFlow<Done> {
1523        self.state[dst].set_i64(i64::from(imm));
1524        ControlFlow::Continue(())
1525    }
1526
1527    fn xzero(&mut self, dst: XReg) -> ControlFlow<Done> {
1528        self.state[dst].set_i64(0);
1529        ControlFlow::Continue(())
1530    }
1531
1532    fn xone(&mut self, dst: XReg) -> ControlFlow<Done> {
1533        self.state[dst].set_i64(1);
1534        ControlFlow::Continue(())
1535    }
1536
1537    fn xconst16(&mut self, dst: XReg, imm: i16) -> ControlFlow<Done> {
1538        self.state[dst].set_i64(i64::from(imm));
1539        ControlFlow::Continue(())
1540    }
1541
1542    fn xconst32(&mut self, dst: XReg, imm: i32) -> ControlFlow<Done> {
1543        self.state[dst].set_i64(i64::from(imm));
1544        ControlFlow::Continue(())
1545    }
1546
1547    fn xconst64(&mut self, dst: XReg, imm: i64) -> ControlFlow<Done> {
1548        self.state[dst].set_i64(imm);
1549        ControlFlow::Continue(())
1550    }
1551
1552    fn xadd32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1553        let a = self.state[operands.src1].get_u32();
1554        let b = self.state[operands.src2].get_u32();
1555        self.state[operands.dst].set_u32(a.wrapping_add(b));
1556        ControlFlow::Continue(())
1557    }
1558
1559    fn xadd32_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1560        self.xadd32_u32(dst, src1, src2.into())
1561    }
1562
1563    fn xadd32_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1564        let a = self.state[src1].get_u32();
1565        self.state[dst].set_u32(a.wrapping_add(src2.into()));
1566        ControlFlow::Continue(())
1567    }
1568
1569    fn xadd64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1570        let a = self.state[operands.src1].get_u64();
1571        let b = self.state[operands.src2].get_u64();
1572        self.state[operands.dst].set_u64(a.wrapping_add(b));
1573        ControlFlow::Continue(())
1574    }
1575
1576    fn xadd64_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1577        self.xadd64_u32(dst, src1, src2.into())
1578    }
1579
1580    fn xadd64_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1581        let a = self.state[src1].get_u64();
1582        self.state[dst].set_u64(a.wrapping_add(src2.into()));
1583        ControlFlow::Continue(())
1584    }
1585
1586    fn xmadd32(&mut self, dst: XReg, src1: XReg, src2: XReg, src3: XReg) -> ControlFlow<Done> {
1587        let a = self.state[src1].get_u32();
1588        let b = self.state[src2].get_u32();
1589        let c = self.state[src3].get_u32();
1590        self.state[dst].set_u32(a.wrapping_mul(b).wrapping_add(c));
1591        ControlFlow::Continue(())
1592    }
1593
1594    fn xmadd64(&mut self, dst: XReg, src1: XReg, src2: XReg, src3: XReg) -> ControlFlow<Done> {
1595        let a = self.state[src1].get_u64();
1596        let b = self.state[src2].get_u64();
1597        let c = self.state[src3].get_u64();
1598        self.state[dst].set_u64(a.wrapping_mul(b).wrapping_add(c));
1599        ControlFlow::Continue(())
1600    }
1601
1602    fn xsub32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1603        let a = self.state[operands.src1].get_u32();
1604        let b = self.state[operands.src2].get_u32();
1605        self.state[operands.dst].set_u32(a.wrapping_sub(b));
1606        ControlFlow::Continue(())
1607    }
1608
1609    fn xsub32_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1610        self.xsub32_u32(dst, src1, src2.into())
1611    }
1612
1613    fn xsub32_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1614        let a = self.state[src1].get_u32();
1615        self.state[dst].set_u32(a.wrapping_sub(src2.into()));
1616        ControlFlow::Continue(())
1617    }
1618
1619    fn xsub64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1620        let a = self.state[operands.src1].get_u64();
1621        let b = self.state[operands.src2].get_u64();
1622        self.state[operands.dst].set_u64(a.wrapping_sub(b));
1623        ControlFlow::Continue(())
1624    }
1625
1626    fn xsub64_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1627        self.xsub64_u32(dst, src1, src2.into())
1628    }
1629
1630    fn xsub64_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1631        let a = self.state[src1].get_u64();
1632        self.state[dst].set_u64(a.wrapping_sub(src2.into()));
1633        ControlFlow::Continue(())
1634    }
1635
1636    fn xmul32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1637        let a = self.state[operands.src1].get_u32();
1638        let b = self.state[operands.src2].get_u32();
1639        self.state[operands.dst].set_u32(a.wrapping_mul(b));
1640        ControlFlow::Continue(())
1641    }
1642
1643    fn xmul32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
1644        self.xmul32_s32(dst, src1, src2.into())
1645    }
1646
1647    fn xmul32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
1648        let a = self.state[src1].get_i32();
1649        self.state[dst].set_i32(a.wrapping_mul(src2));
1650        ControlFlow::Continue(())
1651    }
1652
1653    fn xmul64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1654        let a = self.state[operands.src1].get_u64();
1655        let b = self.state[operands.src2].get_u64();
1656        self.state[operands.dst].set_u64(a.wrapping_mul(b));
1657        ControlFlow::Continue(())
1658    }
1659
1660    fn xmul64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
1661        self.xmul64_s32(dst, src1, src2.into())
1662    }
1663
1664    fn xmul64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
1665        let a = self.state[src1].get_i64();
1666        self.state[dst].set_i64(a.wrapping_mul(src2.into()));
1667        ControlFlow::Continue(())
1668    }
1669
1670    fn xshl32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1671        let a = self.state[operands.src1].get_u32();
1672        let b = self.state[operands.src2].get_u32();
1673        self.state[operands.dst].set_u32(a.wrapping_shl(b));
1674        ControlFlow::Continue(())
1675    }
1676
1677    fn xshr32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1678        let a = self.state[operands.src1].get_u32();
1679        let b = self.state[operands.src2].get_u32();
1680        self.state[operands.dst].set_u32(a.wrapping_shr(b));
1681        ControlFlow::Continue(())
1682    }
1683
1684    fn xshr32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1685        let a = self.state[operands.src1].get_i32();
1686        let b = self.state[operands.src2].get_u32();
1687        self.state[operands.dst].set_i32(a.wrapping_shr(b));
1688        ControlFlow::Continue(())
1689    }
1690
1691    fn xshl64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1692        let a = self.state[operands.src1].get_u64();
1693        let b = self.state[operands.src2].get_u32();
1694        self.state[operands.dst].set_u64(a.wrapping_shl(b));
1695        ControlFlow::Continue(())
1696    }
1697
1698    fn xshr64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1699        let a = self.state[operands.src1].get_u64();
1700        let b = self.state[operands.src2].get_u32();
1701        self.state[operands.dst].set_u64(a.wrapping_shr(b));
1702        ControlFlow::Continue(())
1703    }
1704
1705    fn xshr64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1706        let a = self.state[operands.src1].get_i64();
1707        let b = self.state[operands.src2].get_u32();
1708        self.state[operands.dst].set_i64(a.wrapping_shr(b));
1709        ControlFlow::Continue(())
1710    }
1711
1712    fn xshl32_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1713        let a = self.state[operands.src1].get_u32();
1714        let b = u32::from(u8::from(operands.src2));
1715        self.state[operands.dst].set_u32(a.wrapping_shl(b));
1716        ControlFlow::Continue(())
1717    }
1718
1719    fn xshr32_u_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1720        let a = self.state[operands.src1].get_u32();
1721        let b = u32::from(u8::from(operands.src2));
1722        self.state[operands.dst].set_u32(a.wrapping_shr(b));
1723        ControlFlow::Continue(())
1724    }
1725
1726    fn xshr32_s_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1727        let a = self.state[operands.src1].get_i32();
1728        let b = u32::from(u8::from(operands.src2));
1729        self.state[operands.dst].set_i32(a.wrapping_shr(b));
1730        ControlFlow::Continue(())
1731    }
1732
1733    fn xshl64_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1734        let a = self.state[operands.src1].get_u64();
1735        let b = u32::from(u8::from(operands.src2));
1736        self.state[operands.dst].set_u64(a.wrapping_shl(b));
1737        ControlFlow::Continue(())
1738    }
1739
1740    fn xshr64_u_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1741        let a = self.state[operands.src1].get_u64();
1742        let b = u32::from(u8::from(operands.src2));
1743        self.state[operands.dst].set_u64(a.wrapping_shr(b));
1744        ControlFlow::Continue(())
1745    }
1746
1747    fn xshr64_s_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1748        let a = self.state[operands.src1].get_i64();
1749        let b = u32::from(u8::from(operands.src2));
1750        self.state[operands.dst].set_i64(a.wrapping_shr(b));
1751        ControlFlow::Continue(())
1752    }
1753
1754    fn xneg32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1755        let a = self.state[src].get_i32();
1756        self.state[dst].set_i32(a.wrapping_neg());
1757        ControlFlow::Continue(())
1758    }
1759
1760    fn xneg64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1761        let a = self.state[src].get_i64();
1762        self.state[dst].set_i64(a.wrapping_neg());
1763        ControlFlow::Continue(())
1764    }
1765
1766    fn xeq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1767        let a = self.state[operands.src1].get_u64();
1768        let b = self.state[operands.src2].get_u64();
1769        self.state[operands.dst].set_u32(u32::from(a == b));
1770        ControlFlow::Continue(())
1771    }
1772
1773    fn xneq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1774        let a = self.state[operands.src1].get_u64();
1775        let b = self.state[operands.src2].get_u64();
1776        self.state[operands.dst].set_u32(u32::from(a != b));
1777        ControlFlow::Continue(())
1778    }
1779
1780    fn xslt64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1781        let a = self.state[operands.src1].get_i64();
1782        let b = self.state[operands.src2].get_i64();
1783        self.state[operands.dst].set_u32(u32::from(a < b));
1784        ControlFlow::Continue(())
1785    }
1786
1787    fn xslteq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1788        let a = self.state[operands.src1].get_i64();
1789        let b = self.state[operands.src2].get_i64();
1790        self.state[operands.dst].set_u32(u32::from(a <= b));
1791        ControlFlow::Continue(())
1792    }
1793
1794    fn xult64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1795        let a = self.state[operands.src1].get_u64();
1796        let b = self.state[operands.src2].get_u64();
1797        self.state[operands.dst].set_u32(u32::from(a < b));
1798        ControlFlow::Continue(())
1799    }
1800
1801    fn xulteq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1802        let a = self.state[operands.src1].get_u64();
1803        let b = self.state[operands.src2].get_u64();
1804        self.state[operands.dst].set_u32(u32::from(a <= b));
1805        ControlFlow::Continue(())
1806    }
1807
1808    fn xeq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1809        let a = self.state[operands.src1].get_u32();
1810        let b = self.state[operands.src2].get_u32();
1811        self.state[operands.dst].set_u32(u32::from(a == b));
1812        ControlFlow::Continue(())
1813    }
1814
1815    fn xneq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1816        let a = self.state[operands.src1].get_u32();
1817        let b = self.state[operands.src2].get_u32();
1818        self.state[operands.dst].set_u32(u32::from(a != b));
1819        ControlFlow::Continue(())
1820    }
1821
1822    fn xslt32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1823        let a = self.state[operands.src1].get_i32();
1824        let b = self.state[operands.src2].get_i32();
1825        self.state[operands.dst].set_u32(u32::from(a < b));
1826        ControlFlow::Continue(())
1827    }
1828
1829    fn xslteq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1830        let a = self.state[operands.src1].get_i32();
1831        let b = self.state[operands.src2].get_i32();
1832        self.state[operands.dst].set_u32(u32::from(a <= b));
1833        ControlFlow::Continue(())
1834    }
1835
1836    fn xult32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1837        let a = self.state[operands.src1].get_u32();
1838        let b = self.state[operands.src2].get_u32();
1839        self.state[operands.dst].set_u32(u32::from(a < b));
1840        ControlFlow::Continue(())
1841    }
1842
1843    fn xulteq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1844        let a = self.state[operands.src1].get_u32();
1845        let b = self.state[operands.src2].get_u32();
1846        self.state[operands.dst].set_u32(u32::from(a <= b));
1847        ControlFlow::Continue(())
1848    }
1849
1850    fn xload8_u32_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1851        self.xload8_u32_offset32(dst, ptr, offset.into())
1852    }
1853
1854    fn xload8_s32_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1855        self.xload8_s32_offset32(dst, ptr, offset.into())
1856    }
1857
1858    fn xload16le_u32_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1859        self.xload16le_u32_offset32(dst, ptr, offset.into())
1860    }
1861
1862    fn xload16le_s32_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1863        self.xload16le_s32_offset32(dst, ptr, offset.into())
1864    }
1865
1866    fn xload32le_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1867        self.xload32le_offset32(dst, ptr, offset.into())
1868    }
1869
1870    fn xload8_u64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1871        self.xload8_u64_offset32(dst, ptr, offset.into())
1872    }
1873
1874    fn xload8_s64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1875        self.xload8_s64_offset32(dst, ptr, offset.into())
1876    }
1877
1878    fn xload16le_u64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1879        self.xload16le_u64_offset32(dst, ptr, offset.into())
1880    }
1881
1882    fn xload16le_s64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1883        self.xload16le_s64_offset32(dst, ptr, offset.into())
1884    }
1885
1886    fn xload32le_u64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1887        self.xload32le_u64_offset32(dst, ptr, offset.into())
1888    }
1889
1890    fn xload32le_s64_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1891        self.xload32le_s64_offset32(dst, ptr, offset.into())
1892    }
1893
1894    fn xload64le_offset8(&mut self, dst: XReg, ptr: XReg, offset: u8) -> ControlFlow<Done> {
1895        self.xload64le_offset32(dst, ptr, offset.into())
1896    }
1897
1898    fn xstore8_offset8(&mut self, ptr: XReg, offset: u8, src: XReg) -> ControlFlow<Done> {
1899        self.xstore8_offset32(ptr, offset.into(), src)
1900    }
1901
1902    fn xstore16le_offset8(&mut self, ptr: XReg, offset: u8, src: XReg) -> ControlFlow<Done> {
1903        self.xstore16le_offset32(ptr, offset.into(), src)
1904    }
1905
1906    fn xstore32le_offset8(&mut self, ptr: XReg, offset: u8, src: XReg) -> ControlFlow<Done> {
1907        self.xstore32le_offset32(ptr, offset.into(), src)
1908    }
1909
1910    fn xstore64le_offset8(&mut self, ptr: XReg, offset: u8, src: XReg) -> ControlFlow<Done> {
1911        self.xstore64le_offset32(ptr, offset.into(), src)
1912    }
1913
1914    fn xload8_u32_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1915        let val = unsafe { self.load::<u8>(ptr, offset) };
1916        self.state[dst].set_u32(val.into());
1917        ControlFlow::Continue(())
1918    }
1919
1920    fn xload8_s32_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1921        let val = unsafe { self.load::<i8>(ptr, offset) };
1922        self.state[dst].set_i32(val.into());
1923        ControlFlow::Continue(())
1924    }
1925
1926    fn xload16le_u32_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1927        let val = unsafe { self.load::<u16>(ptr, offset) };
1928        self.state[dst].set_u32(u16::from_le(val).into());
1929        ControlFlow::Continue(())
1930    }
1931
1932    fn xload16le_s32_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1933        let val = unsafe { self.load::<i16>(ptr, offset) };
1934        self.state[dst].set_i32(i16::from_le(val).into());
1935        ControlFlow::Continue(())
1936    }
1937
1938    fn xload32le_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1939        let val = unsafe { self.load::<i32>(ptr, offset) };
1940        self.state[dst].set_i32(i32::from_le(val));
1941        ControlFlow::Continue(())
1942    }
1943
1944    fn xload8_u64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1945        let val = unsafe { self.load::<u8>(ptr, offset) };
1946        self.state[dst].set_u64(val.into());
1947        ControlFlow::Continue(())
1948    }
1949
1950    fn xload8_s64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1951        let val = unsafe { self.load::<i8>(ptr, offset) };
1952        self.state[dst].set_i64(val.into());
1953        ControlFlow::Continue(())
1954    }
1955
1956    fn xload16le_u64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1957        let val = unsafe { self.load::<u16>(ptr, offset) };
1958        self.state[dst].set_u64(u16::from_le(val).into());
1959        ControlFlow::Continue(())
1960    }
1961
1962    fn xload16le_s64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1963        let val = unsafe { self.load::<i16>(ptr, offset) };
1964        self.state[dst].set_i64(i16::from_le(val).into());
1965        ControlFlow::Continue(())
1966    }
1967
1968    fn xload32le_u64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1969        let val = unsafe { self.load::<u32>(ptr, offset) };
1970        self.state[dst].set_u64(u32::from_le(val).into());
1971        ControlFlow::Continue(())
1972    }
1973
1974    fn xload32le_s64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1975        let val = unsafe { self.load::<i32>(ptr, offset) };
1976        self.state[dst].set_i64(i32::from_le(val).into());
1977        ControlFlow::Continue(())
1978    }
1979
1980    fn xload64le_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
1981        let val = unsafe { self.load::<i64>(ptr, offset) };
1982        self.state[dst].set_i64(i64::from_le(val));
1983        ControlFlow::Continue(())
1984    }
1985
1986    fn xstore8_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
1987        let val = self.state[src].get_u32() as u8;
1988        unsafe {
1989            self.store(ptr, offset, val);
1990        }
1991        ControlFlow::Continue(())
1992    }
1993
1994    fn xstore16le_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
1995        let val = self.state[src].get_u32() as u16;
1996        unsafe {
1997            self.store(ptr, offset, val.to_le());
1998        }
1999        ControlFlow::Continue(())
2000    }
2001
2002    fn xstore32le_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
2003        let val = self.state[src].get_u32();
2004        unsafe {
2005            self.store(ptr, offset, val.to_le());
2006        }
2007        ControlFlow::Continue(())
2008    }
2009
2010    fn xstore64le_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
2011        let val = self.state[src].get_u64();
2012        unsafe {
2013            self.store(ptr, offset, val.to_le());
2014        }
2015        ControlFlow::Continue(())
2016    }
2017
2018    fn push_frame(&mut self) -> ControlFlow<Done> {
2019        self.push::<crate::PushFrame, _>(self.state.lr)?;
2020        self.push::<crate::PushFrame, _>(self.state.fp)?;
2021        self.state.fp = self.state[XReg::sp].get_ptr();
2022        ControlFlow::Continue(())
2023    }
2024
2025    #[inline]
2026    fn push_frame_save(&mut self, amt: u16, regs: UpperRegSet<XReg>) -> ControlFlow<Done> {
2027        // Decrement the stack pointer `amt` bytes plus 2 pointers more for
2028        // fp/lr.
2029        let ptr_size = size_of::<usize>();
2030        let full_amt = usize::from(amt) + 2 * ptr_size;
2031        let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_sub(full_amt);
2032        self.set_sp::<crate::PushFrameSave>(new_sp)?;
2033
2034        unsafe {
2035            // Emulate `push_frame` by placing `lr` and `fp` onto the stack, in
2036            // that order, at the top of the allocated area.
2037            self.store(XReg::sp, (full_amt - 1 * ptr_size) as i32, self.state.lr);
2038            self.store(XReg::sp, (full_amt - 2 * ptr_size) as i32, self.state.fp);
2039
2040            // Set `fp` to the top of our frame, where `fp` is stored.
2041            let mut offset = amt as i32;
2042            self.state.fp = self.state[XReg::sp]
2043                .get_ptr::<u8>()
2044                .byte_offset(offset as isize);
2045
2046            // Next save any registers in `regs` to the stack.
2047            for reg in regs {
2048                offset -= 8;
2049                self.store(XReg::sp, offset, self.state[reg].get_u64());
2050            }
2051        }
2052        ControlFlow::Continue(())
2053    }
2054
2055    fn pop_frame_restore(&mut self, amt: u16, regs: UpperRegSet<XReg>) -> ControlFlow<Done> {
2056        // Restore all registers in `regs`, followed by the normal `pop_frame`
2057        // opcode below to restore fp/lr.
2058        unsafe {
2059            let mut offset = i32::from(amt);
2060            for reg in regs {
2061                offset -= 8;
2062                let val = self.load(XReg::sp, offset);
2063                self.state[reg].set_u64(val);
2064            }
2065        }
2066        self.pop_frame()
2067    }
2068
2069    fn pop_frame(&mut self) -> ControlFlow<Done> {
2070        self.set_sp_unchecked(self.state.fp);
2071        let fp = self.pop();
2072        let lr = self.pop();
2073        self.state.fp = fp;
2074        self.state.lr = lr;
2075        ControlFlow::Continue(())
2076    }
2077
2078    fn br_table32(&mut self, idx: XReg, amt: u32) -> ControlFlow<Done> {
2079        let idx = self.state[idx].get_u32().min(amt - 1) as isize;
2080        // SAFETY: part of the contract of the interpreter is only dealing with
2081        // valid bytecode, so this offset should be safe.
2082        self.pc = unsafe { self.pc.offset(idx * 4) };
2083
2084        // Decode the `PcRelOffset` without tampering with `self.pc` as the
2085        // jump is relative to `self.pc`.
2086        let mut tmp = self.pc;
2087        let Ok(rel) = PcRelOffset::decode(&mut tmp);
2088        let offset = isize::try_from(i32::from(rel)).unwrap();
2089        self.pc = unsafe { self.pc.offset(offset) };
2090        ControlFlow::Continue(())
2091    }
2092
2093    fn stack_alloc32(&mut self, amt: u32) -> ControlFlow<Done> {
2094        let amt = usize::try_from(amt).unwrap();
2095        let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_sub(amt);
2096        self.set_sp::<crate::StackAlloc32>(new_sp)?;
2097        ControlFlow::Continue(())
2098    }
2099
2100    fn stack_free32(&mut self, amt: u32) -> ControlFlow<Done> {
2101        let amt = usize::try_from(amt).unwrap();
2102        let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_add(amt);
2103        self.set_sp_unchecked(new_sp);
2104        ControlFlow::Continue(())
2105    }
2106
2107    fn zext8(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2108        let src = self.state[src].get_u64() as u8;
2109        self.state[dst].set_u64(src.into());
2110        ControlFlow::Continue(())
2111    }
2112
2113    fn zext16(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2114        let src = self.state[src].get_u64() as u16;
2115        self.state[dst].set_u64(src.into());
2116        ControlFlow::Continue(())
2117    }
2118
2119    fn zext32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2120        let src = self.state[src].get_u64() as u32;
2121        self.state[dst].set_u64(src.into());
2122        ControlFlow::Continue(())
2123    }
2124
2125    fn sext8(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2126        let src = self.state[src].get_i64() as i8;
2127        self.state[dst].set_i64(src.into());
2128        ControlFlow::Continue(())
2129    }
2130
2131    fn sext16(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2132        let src = self.state[src].get_i64() as i16;
2133        self.state[dst].set_i64(src.into());
2134        ControlFlow::Continue(())
2135    }
2136
2137    fn sext32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2138        let src = self.state[src].get_i64() as i32;
2139        self.state[dst].set_i64(src.into());
2140        ControlFlow::Continue(())
2141    }
2142
2143    fn xdiv32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2144        let a = self.state[operands.src1].get_i32();
2145        let b = self.state[operands.src2].get_i32();
2146        match a.checked_div(b) {
2147            Some(result) => {
2148                self.state[operands.dst].set_i32(result);
2149                ControlFlow::Continue(())
2150            }
2151            None => {
2152                let kind = if b == 0 {
2153                    TrapKind::DivideByZero
2154                } else {
2155                    TrapKind::IntegerOverflow
2156                };
2157                self.done_trap_kind::<crate::XDiv32S>(Some(kind))
2158            }
2159        }
2160    }
2161
2162    fn xdiv64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2163        let a = self.state[operands.src1].get_i64();
2164        let b = self.state[operands.src2].get_i64();
2165        match a.checked_div(b) {
2166            Some(result) => {
2167                self.state[operands.dst].set_i64(result);
2168                ControlFlow::Continue(())
2169            }
2170            None => {
2171                let kind = if b == 0 {
2172                    TrapKind::DivideByZero
2173                } else {
2174                    TrapKind::IntegerOverflow
2175                };
2176                self.done_trap_kind::<crate::XDiv64S>(Some(kind))
2177            }
2178        }
2179    }
2180
2181    fn xdiv32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2182        let a = self.state[operands.src1].get_u32();
2183        let b = self.state[operands.src2].get_u32();
2184        match a.checked_div(b) {
2185            Some(result) => {
2186                self.state[operands.dst].set_u32(result);
2187                ControlFlow::Continue(())
2188            }
2189            None => self.done_trap_kind::<crate::XDiv64U>(Some(TrapKind::DivideByZero)),
2190        }
2191    }
2192
2193    fn xdiv64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2194        let a = self.state[operands.src1].get_u64();
2195        let b = self.state[operands.src2].get_u64();
2196        match a.checked_div(b) {
2197            Some(result) => {
2198                self.state[operands.dst].set_u64(result);
2199                ControlFlow::Continue(())
2200            }
2201            None => self.done_trap_kind::<crate::XDiv64U>(Some(TrapKind::DivideByZero)),
2202        }
2203    }
2204
2205    fn xrem32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2206        let a = self.state[operands.src1].get_i32();
2207        let b = self.state[operands.src2].get_i32();
2208        let result = if a == i32::MIN && b == -1 {
2209            Some(0)
2210        } else {
2211            a.checked_rem(b)
2212        };
2213        match result {
2214            Some(result) => {
2215                self.state[operands.dst].set_i32(result);
2216                ControlFlow::Continue(())
2217            }
2218            None => self.done_trap_kind::<crate::XRem32S>(Some(TrapKind::DivideByZero)),
2219        }
2220    }
2221
2222    fn xrem64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2223        let a = self.state[operands.src1].get_i64();
2224        let b = self.state[operands.src2].get_i64();
2225        let result = if a == i64::MIN && b == -1 {
2226            Some(0)
2227        } else {
2228            a.checked_rem(b)
2229        };
2230        match result {
2231            Some(result) => {
2232                self.state[operands.dst].set_i64(result);
2233                ControlFlow::Continue(())
2234            }
2235            None => self.done_trap_kind::<crate::XRem64S>(Some(TrapKind::DivideByZero)),
2236        }
2237    }
2238
2239    fn xrem32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2240        let a = self.state[operands.src1].get_u32();
2241        let b = self.state[operands.src2].get_u32();
2242        match a.checked_rem(b) {
2243            Some(result) => {
2244                self.state[operands.dst].set_u32(result);
2245                ControlFlow::Continue(())
2246            }
2247            None => self.done_trap_kind::<crate::XRem32U>(Some(TrapKind::DivideByZero)),
2248        }
2249    }
2250
2251    fn xrem64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2252        let a = self.state[operands.src1].get_u64();
2253        let b = self.state[operands.src2].get_u64();
2254        match a.checked_rem(b) {
2255            Some(result) => {
2256                self.state[operands.dst].set_u64(result);
2257                ControlFlow::Continue(())
2258            }
2259            None => self.done_trap_kind::<crate::XRem64U>(Some(TrapKind::DivideByZero)),
2260        }
2261    }
2262
2263    fn xband32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2264        let a = self.state[operands.src1].get_u32();
2265        let b = self.state[operands.src2].get_u32();
2266        self.state[operands.dst].set_u32(a & b);
2267        ControlFlow::Continue(())
2268    }
2269
2270    fn xband32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2271        self.xband32_s32(dst, src1, src2.into())
2272    }
2273
2274    fn xband32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2275        let a = self.state[src1].get_i32();
2276        self.state[dst].set_i32(a & src2);
2277        ControlFlow::Continue(())
2278    }
2279
2280    fn xband64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2281        let a = self.state[operands.src1].get_u64();
2282        let b = self.state[operands.src2].get_u64();
2283        self.state[operands.dst].set_u64(a & b);
2284        ControlFlow::Continue(())
2285    }
2286
2287    fn xband64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2288        self.xband64_s32(dst, src1, src2.into())
2289    }
2290
2291    fn xband64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2292        let a = self.state[src1].get_i64();
2293        self.state[dst].set_i64(a & i64::from(src2));
2294        ControlFlow::Continue(())
2295    }
2296
2297    fn xbor32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2298        let a = self.state[operands.src1].get_u32();
2299        let b = self.state[operands.src2].get_u32();
2300        self.state[operands.dst].set_u32(a | b);
2301        ControlFlow::Continue(())
2302    }
2303
2304    fn xbor32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2305        self.xbor32_s32(dst, src1, src2.into())
2306    }
2307
2308    fn xbor32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2309        let a = self.state[src1].get_i32();
2310        self.state[dst].set_i32(a | src2);
2311        ControlFlow::Continue(())
2312    }
2313
2314    fn xbor64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2315        let a = self.state[operands.src1].get_u64();
2316        let b = self.state[operands.src2].get_u64();
2317        self.state[operands.dst].set_u64(a | b);
2318        ControlFlow::Continue(())
2319    }
2320
2321    fn xbor64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2322        self.xbor64_s32(dst, src1, src2.into())
2323    }
2324
2325    fn xbor64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2326        let a = self.state[src1].get_i64();
2327        self.state[dst].set_i64(a | i64::from(src2));
2328        ControlFlow::Continue(())
2329    }
2330
2331    fn xbxor32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2332        let a = self.state[operands.src1].get_u32();
2333        let b = self.state[operands.src2].get_u32();
2334        self.state[operands.dst].set_u32(a ^ b);
2335        ControlFlow::Continue(())
2336    }
2337
2338    fn xbxor32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2339        self.xbxor32_s32(dst, src1, src2.into())
2340    }
2341
2342    fn xbxor32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2343        let a = self.state[src1].get_i32();
2344        self.state[dst].set_i32(a ^ src2);
2345        ControlFlow::Continue(())
2346    }
2347
2348    fn xbxor64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2349        let a = self.state[operands.src1].get_u64();
2350        let b = self.state[operands.src2].get_u64();
2351        self.state[operands.dst].set_u64(a ^ b);
2352        ControlFlow::Continue(())
2353    }
2354
2355    fn xbxor64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2356        self.xbxor64_s32(dst, src1, src2.into())
2357    }
2358
2359    fn xbxor64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2360        let a = self.state[src1].get_i64();
2361        self.state[dst].set_i64(a ^ i64::from(src2));
2362        ControlFlow::Continue(())
2363    }
2364
2365    fn xbnot32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2366        let a = self.state[src].get_u32();
2367        self.state[dst].set_u32(!a);
2368        ControlFlow::Continue(())
2369    }
2370
2371    fn xbnot64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2372        let a = self.state[src].get_u64();
2373        self.state[dst].set_u64(!a);
2374        ControlFlow::Continue(())
2375    }
2376
2377    fn xmin32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2378        let a = self.state[operands.src1].get_u32();
2379        let b = self.state[operands.src2].get_u32();
2380        self.state[operands.dst].set_u32(a.min(b));
2381        ControlFlow::Continue(())
2382    }
2383
2384    fn xmin32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2385        let a = self.state[operands.src1].get_i32();
2386        let b = self.state[operands.src2].get_i32();
2387        self.state[operands.dst].set_i32(a.min(b));
2388        ControlFlow::Continue(())
2389    }
2390
2391    fn xmax32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2392        let a = self.state[operands.src1].get_u32();
2393        let b = self.state[operands.src2].get_u32();
2394        self.state[operands.dst].set_u32(a.max(b));
2395        ControlFlow::Continue(())
2396    }
2397
2398    fn xmax32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2399        let a = self.state[operands.src1].get_i32();
2400        let b = self.state[operands.src2].get_i32();
2401        self.state[operands.dst].set_i32(a.max(b));
2402        ControlFlow::Continue(())
2403    }
2404
2405    fn xmin64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2406        let a = self.state[operands.src1].get_u64();
2407        let b = self.state[operands.src2].get_u64();
2408        self.state[operands.dst].set_u64(a.min(b));
2409        ControlFlow::Continue(())
2410    }
2411
2412    fn xmin64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2413        let a = self.state[operands.src1].get_i64();
2414        let b = self.state[operands.src2].get_i64();
2415        self.state[operands.dst].set_i64(a.min(b));
2416        ControlFlow::Continue(())
2417    }
2418
2419    fn xmax64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2420        let a = self.state[operands.src1].get_u64();
2421        let b = self.state[operands.src2].get_u64();
2422        self.state[operands.dst].set_u64(a.max(b));
2423        ControlFlow::Continue(())
2424    }
2425
2426    fn xmax64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2427        let a = self.state[operands.src1].get_i64();
2428        let b = self.state[operands.src2].get_i64();
2429        self.state[operands.dst].set_i64(a.max(b));
2430        ControlFlow::Continue(())
2431    }
2432
2433    fn xctz32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2434        let a = self.state[src].get_u32();
2435        self.state[dst].set_u32(a.trailing_zeros());
2436        ControlFlow::Continue(())
2437    }
2438
2439    fn xctz64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2440        let a = self.state[src].get_u64();
2441        self.state[dst].set_u64(a.trailing_zeros().into());
2442        ControlFlow::Continue(())
2443    }
2444
2445    fn xclz32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2446        let a = self.state[src].get_u32();
2447        self.state[dst].set_u32(a.leading_zeros());
2448        ControlFlow::Continue(())
2449    }
2450
2451    fn xclz64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2452        let a = self.state[src].get_u64();
2453        self.state[dst].set_u64(a.leading_zeros().into());
2454        ControlFlow::Continue(())
2455    }
2456
2457    fn xpopcnt32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2458        let a = self.state[src].get_u32();
2459        self.state[dst].set_u32(a.count_ones());
2460        ControlFlow::Continue(())
2461    }
2462
2463    fn xpopcnt64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2464        let a = self.state[src].get_u64();
2465        self.state[dst].set_u64(a.count_ones().into());
2466        ControlFlow::Continue(())
2467    }
2468
2469    fn xrotl32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2470        let a = self.state[operands.src1].get_u32();
2471        let b = self.state[operands.src2].get_u32();
2472        self.state[operands.dst].set_u32(a.rotate_left(b));
2473        ControlFlow::Continue(())
2474    }
2475
2476    fn xrotl64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2477        let a = self.state[operands.src1].get_u64();
2478        let b = self.state[operands.src2].get_u32();
2479        self.state[operands.dst].set_u64(a.rotate_left(b));
2480        ControlFlow::Continue(())
2481    }
2482
2483    fn xrotr32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2484        let a = self.state[operands.src1].get_u32();
2485        let b = self.state[operands.src2].get_u32();
2486        self.state[operands.dst].set_u32(a.rotate_right(b));
2487        ControlFlow::Continue(())
2488    }
2489
2490    fn xrotr64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2491        let a = self.state[operands.src1].get_u64();
2492        let b = self.state[operands.src2].get_u32();
2493        self.state[operands.dst].set_u64(a.rotate_right(b));
2494        ControlFlow::Continue(())
2495    }
2496
2497    fn xselect32(
2498        &mut self,
2499        dst: XReg,
2500        cond: XReg,
2501        if_nonzero: XReg,
2502        if_zero: XReg,
2503    ) -> ControlFlow<Done> {
2504        let result = if self.state[cond].get_u32() != 0 {
2505            self.state[if_nonzero].get_u32()
2506        } else {
2507            self.state[if_zero].get_u32()
2508        };
2509        self.state[dst].set_u32(result);
2510        ControlFlow::Continue(())
2511    }
2512
2513    fn xselect64(
2514        &mut self,
2515        dst: XReg,
2516        cond: XReg,
2517        if_nonzero: XReg,
2518        if_zero: XReg,
2519    ) -> ControlFlow<Done> {
2520        let result = if self.state[cond].get_u32() != 0 {
2521            self.state[if_nonzero].get_u64()
2522        } else {
2523            self.state[if_zero].get_u64()
2524        };
2525        self.state[dst].set_u64(result);
2526        ControlFlow::Continue(())
2527    }
2528
2529    fn xabs32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2530        let a = self.state[src].get_i32();
2531        self.state[dst].set_i32(a.wrapping_abs());
2532        ControlFlow::Continue(())
2533    }
2534
2535    fn xabs64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2536        let a = self.state[src].get_i64();
2537        self.state[dst].set_i64(a.wrapping_abs());
2538        ControlFlow::Continue(())
2539    }
2540
2541    fn xbc32_bound_trap(&mut self, addr: XReg, bound: XReg, size: u8) -> ControlFlow<Done> {
2542        let bound = self.state[bound].get_u64() as usize;
2543        let addr = self.state[addr].get_u32() as usize;
2544        if addr > bound.wrapping_sub(usize::from(size)) {
2545            self.done_trap::<crate::XBc32BoundTrap>()
2546        } else {
2547            ControlFlow::Continue(())
2548        }
2549    }
2550
2551    fn xbc32_boundne_trap(
2552        &mut self,
2553        addr: XReg,
2554        bound_ptr: XReg,
2555        bound_off: u8,
2556        size: u8,
2557    ) -> ControlFlow<Done> {
2558        let bound = unsafe { self.load::<usize>(bound_ptr, bound_off.into()) };
2559        let addr = self.state[addr].get_u32() as usize;
2560        if addr > bound.wrapping_sub(usize::from(size)) {
2561            self.done_trap::<crate::XBc32BoundNeTrap>()
2562        } else {
2563            ControlFlow::Continue(())
2564        }
2565    }
2566
2567    fn xbc32_strict_bound_trap(&mut self, addr: XReg, bound: XReg) -> ControlFlow<Done> {
2568        let bound = self.state[bound].get_u64() as usize;
2569        let addr = self.state[addr].get_u32() as usize;
2570        if addr >= bound {
2571            self.done_trap::<crate::XBc32StrictBoundTrap>()
2572        } else {
2573            ControlFlow::Continue(())
2574        }
2575    }
2576
2577    fn xbc32_strict_boundne_trap(
2578        &mut self,
2579        addr: XReg,
2580        bound_ptr: XReg,
2581        bound_off: u8,
2582    ) -> ControlFlow<Done> {
2583        let bound = unsafe { self.load::<usize>(bound_ptr, bound_off.into()) };
2584        let addr = self.state[addr].get_u32() as usize;
2585        if addr >= bound {
2586            self.done_trap::<crate::XBc32StrictBoundNeTrap>()
2587        } else {
2588            ControlFlow::Continue(())
2589        }
2590    }
2591
2592    fn xload8_u32_g32(
2593        &mut self,
2594        dst: XReg,
2595        base: XReg,
2596        addr: XReg,
2597        offset: u8,
2598    ) -> ControlFlow<Done> {
2599        let result = unsafe { self.load_g32::<u8>(base, addr, offset) };
2600        self.state[dst].set_u32(result.into());
2601        ControlFlow::Continue(())
2602    }
2603
2604    fn xload8_s32_g32(
2605        &mut self,
2606        dst: XReg,
2607        base: XReg,
2608        addr: XReg,
2609        offset: u8,
2610    ) -> ControlFlow<Done> {
2611        let result = unsafe { self.load_g32::<i8>(base, addr, offset) };
2612        self.state[dst].set_i32(result.into());
2613        ControlFlow::Continue(())
2614    }
2615
2616    fn xload16le_u32_g32(
2617        &mut self,
2618        dst: XReg,
2619        base: XReg,
2620        addr: XReg,
2621        offset: u8,
2622    ) -> ControlFlow<Done> {
2623        let result = unsafe { self.load_g32::<u16>(base, addr, offset) };
2624        self.state[dst].set_u32(u16::from_le(result).into());
2625        ControlFlow::Continue(())
2626    }
2627
2628    fn xload16le_s32_g32(
2629        &mut self,
2630        dst: XReg,
2631        base: XReg,
2632        addr: XReg,
2633        offset: u8,
2634    ) -> ControlFlow<Done> {
2635        let result = unsafe { self.load_g32::<i16>(base, addr, offset) };
2636        self.state[dst].set_i32(i16::from_le(result).into());
2637        ControlFlow::Continue(())
2638    }
2639
2640    fn xload32le_g32(
2641        &mut self,
2642        dst: XReg,
2643        base: XReg,
2644        addr: XReg,
2645        offset: u8,
2646    ) -> ControlFlow<Done> {
2647        let result = unsafe { self.load_g32::<i32>(base, addr, offset) };
2648        self.state[dst].set_i32(i32::from_le(result));
2649        ControlFlow::Continue(())
2650    }
2651
2652    fn xload64le_g32(
2653        &mut self,
2654        dst: XReg,
2655        base: XReg,
2656        addr: XReg,
2657        offset: u8,
2658    ) -> ControlFlow<Done> {
2659        let result = unsafe { self.load_g32::<i64>(base, addr, offset) };
2660        self.state[dst].set_i64(i64::from_le(result));
2661        ControlFlow::Continue(())
2662    }
2663
2664    fn xstore8_g32(&mut self, base: XReg, addr: XReg, offset: u8, val: XReg) -> ControlFlow<Done> {
2665        let val = self.state[val].get_u32() as u8;
2666        unsafe {
2667            self.store_g32(base, addr, offset, val);
2668        }
2669        ControlFlow::Continue(())
2670    }
2671
2672    fn xstore16le_g32(
2673        &mut self,
2674        base: XReg,
2675        addr: XReg,
2676        offset: u8,
2677        val: XReg,
2678    ) -> ControlFlow<Done> {
2679        let val = self.state[val].get_u32() as u16;
2680        unsafe {
2681            self.store_g32(base, addr, offset, val.to_le());
2682        }
2683        ControlFlow::Continue(())
2684    }
2685
2686    fn xstore32le_g32(
2687        &mut self,
2688        base: XReg,
2689        addr: XReg,
2690        offset: u8,
2691        val: XReg,
2692    ) -> ControlFlow<Done> {
2693        let val = self.state[val].get_u32();
2694        unsafe {
2695            self.store_g32(base, addr, offset, val.to_le());
2696        }
2697        ControlFlow::Continue(())
2698    }
2699
2700    fn xstore64le_g32(
2701        &mut self,
2702        base: XReg,
2703        addr: XReg,
2704        offset: u8,
2705        val: XReg,
2706    ) -> ControlFlow<Done> {
2707        let val = self.state[val].get_u64();
2708        unsafe {
2709            self.store_g32(base, addr, offset, val.to_le());
2710        }
2711        ControlFlow::Continue(())
2712    }
2713}
2714
2715impl ExtendedOpVisitor for Interpreter<'_> {
2716    fn nop(&mut self) -> ControlFlow<Done> {
2717        ControlFlow::Continue(())
2718    }
2719
2720    fn trap(&mut self) -> ControlFlow<Done> {
2721        self.done_trap::<crate::Trap>()
2722    }
2723
2724    fn call_indirect_host(&mut self, id: u8) -> ControlFlow<Done> {
2725        self.done_call_indirect_host(id)
2726    }
2727
2728    fn bswap32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2729        let src = self.state[src].get_u32();
2730        self.state[dst].set_u32(src.swap_bytes());
2731        ControlFlow::Continue(())
2732    }
2733
2734    fn bswap64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2735        let src = self.state[src].get_u64();
2736        self.state[dst].set_u64(src.swap_bytes());
2737        ControlFlow::Continue(())
2738    }
2739
2740    fn xbmask32(&mut self, dst: XReg, src: XReg) -> Self::Return {
2741        let a = self.state[src].get_u32();
2742        if a == 0 {
2743            self.state[dst].set_u32(0);
2744        } else {
2745            self.state[dst].set_i32(-1);
2746        }
2747        ControlFlow::Continue(())
2748    }
2749
2750    fn xbmask64(&mut self, dst: XReg, src: XReg) -> Self::Return {
2751        let a = self.state[src].get_u64();
2752        if a == 0 {
2753            self.state[dst].set_u64(0);
2754        } else {
2755            self.state[dst].set_i64(-1);
2756        }
2757        ControlFlow::Continue(())
2758    }
2759
2760    fn xadd32_uoverflow_trap(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2761        let a = self.state[operands.src1].get_u32();
2762        let b = self.state[operands.src2].get_u32();
2763        match a.checked_add(b) {
2764            Some(c) => {
2765                self.state[operands.dst].set_u32(c);
2766                ControlFlow::Continue(())
2767            }
2768            None => self.done_trap::<crate::Xadd32UoverflowTrap>(),
2769        }
2770    }
2771
2772    fn xadd64_uoverflow_trap(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2773        let a = self.state[operands.src1].get_u64();
2774        let b = self.state[operands.src2].get_u64();
2775        match a.checked_add(b) {
2776            Some(c) => {
2777                self.state[operands.dst].set_u64(c);
2778                ControlFlow::Continue(())
2779            }
2780            None => self.done_trap::<crate::Xadd64UoverflowTrap>(),
2781        }
2782    }
2783
2784    fn xmulhi64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2785        let a = self.state[operands.src1].get_i64();
2786        let b = self.state[operands.src2].get_i64();
2787        let result = ((i128::from(a) * i128::from(b)) >> 64) as i64;
2788        self.state[operands.dst].set_i64(result);
2789        ControlFlow::Continue(())
2790    }
2791
2792    fn xmulhi64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2793        let a = self.state[operands.src1].get_u64();
2794        let b = self.state[operands.src2].get_u64();
2795        let result = ((u128::from(a) * u128::from(b)) >> 64) as u64;
2796        self.state[operands.dst].set_u64(result);
2797        ControlFlow::Continue(())
2798    }
2799
2800    fn xload16be_u64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2801        let val = unsafe { self.load::<u16>(ptr, offset) };
2802        self.state[dst].set_u64(u16::from_be(val).into());
2803        ControlFlow::Continue(())
2804    }
2805
2806    fn xload16be_s64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2807        let val = unsafe { self.load::<i16>(ptr, offset) };
2808        self.state[dst].set_i64(i16::from_be(val).into());
2809        ControlFlow::Continue(())
2810    }
2811
2812    fn xload32be_u64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2813        let val = unsafe { self.load::<u32>(ptr, offset) };
2814        self.state[dst].set_u64(u32::from_be(val).into());
2815        ControlFlow::Continue(())
2816    }
2817
2818    fn xload32be_s64_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2819        let val = unsafe { self.load::<i32>(ptr, offset) };
2820        self.state[dst].set_i64(i32::from_be(val).into());
2821        ControlFlow::Continue(())
2822    }
2823
2824    fn xload64be_offset32(&mut self, dst: XReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2825        let val = unsafe { self.load::<i64>(ptr, offset) };
2826        self.state[dst].set_i64(i64::from_be(val));
2827        ControlFlow::Continue(())
2828    }
2829
2830    fn xstore16be_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
2831        let val = self.state[src].get_u32() as u16;
2832        unsafe {
2833            self.store(ptr, offset, val.to_be());
2834        }
2835        ControlFlow::Continue(())
2836    }
2837
2838    fn xstore32be_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
2839        let val = self.state[src].get_u32();
2840        unsafe {
2841            self.store(ptr, offset, val.to_be());
2842        }
2843        ControlFlow::Continue(())
2844    }
2845
2846    fn xstore64be_offset32(&mut self, ptr: XReg, offset: i32, src: XReg) -> ControlFlow<Done> {
2847        let val = self.state[src].get_u64();
2848        unsafe {
2849            self.store(ptr, offset, val.to_be());
2850        }
2851        ControlFlow::Continue(())
2852    }
2853
2854    fn fload32be_offset32(&mut self, dst: FReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2855        let val = unsafe { self.load::<u32>(ptr, offset) };
2856        self.state[dst].set_f32(f32::from_bits(u32::from_be(val)));
2857        ControlFlow::Continue(())
2858    }
2859
2860    fn fload64be_offset32(&mut self, dst: FReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2861        let val = unsafe { self.load::<u64>(ptr, offset) };
2862        self.state[dst].set_f64(f64::from_bits(u64::from_be(val)));
2863        ControlFlow::Continue(())
2864    }
2865
2866    fn fstore32be_offset32(&mut self, ptr: XReg, offset: i32, src: FReg) -> ControlFlow<Done> {
2867        let val = self.state[src].get_f32();
2868        unsafe {
2869            self.store(ptr, offset, val.to_bits().to_be());
2870        }
2871        ControlFlow::Continue(())
2872    }
2873
2874    fn fstore64be_offset32(&mut self, ptr: XReg, offset: i32, src: FReg) -> ControlFlow<Done> {
2875        let val = self.state[src].get_f64();
2876        unsafe {
2877            self.store(ptr, offset, val.to_bits().to_be());
2878        }
2879        ControlFlow::Continue(())
2880    }
2881
2882    fn fload32le_offset32(&mut self, dst: FReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2883        let val = unsafe { self.load::<u32>(ptr, offset) };
2884        self.state[dst].set_f32(f32::from_bits(u32::from_le(val)));
2885        ControlFlow::Continue(())
2886    }
2887
2888    fn fload64le_offset32(&mut self, dst: FReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2889        let val = unsafe { self.load::<u64>(ptr, offset) };
2890        self.state[dst].set_f64(f64::from_bits(u64::from_le(val)));
2891        ControlFlow::Continue(())
2892    }
2893
2894    fn fstore32le_offset32(&mut self, ptr: XReg, offset: i32, src: FReg) -> ControlFlow<Done> {
2895        let val = self.state[src].get_f32();
2896        unsafe {
2897            self.store(ptr, offset, val.to_bits().to_le());
2898        }
2899        ControlFlow::Continue(())
2900    }
2901
2902    fn fstore64le_offset32(&mut self, ptr: XReg, offset: i32, src: FReg) -> ControlFlow<Done> {
2903        let val = self.state[src].get_f64();
2904        unsafe {
2905            self.store(ptr, offset, val.to_bits().to_le());
2906        }
2907        ControlFlow::Continue(())
2908    }
2909
2910    fn vload128le_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
2911        let val = unsafe { self.load::<u128>(ptr, offset) };
2912        self.state[dst].set_u128(u128::from_le(val));
2913        ControlFlow::Continue(())
2914    }
2915
2916    fn vstore128le_offset32(&mut self, ptr: XReg, offset: i32, src: VReg) -> ControlFlow<Done> {
2917        let val = self.state[src].get_u128();
2918        unsafe {
2919            self.store(ptr, offset, val.to_le());
2920        }
2921        ControlFlow::Continue(())
2922    }
2923
2924    fn xmov_fp(&mut self, dst: XReg) -> ControlFlow<Done> {
2925        let fp = self.state.fp;
2926        self.state[dst].set_ptr(fp);
2927        ControlFlow::Continue(())
2928    }
2929
2930    fn xmov_lr(&mut self, dst: XReg) -> ControlFlow<Done> {
2931        let lr = self.state.lr;
2932        self.state[dst].set_ptr(lr);
2933        ControlFlow::Continue(())
2934    }
2935
2936    fn fmov(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
2937        let val = self.state[src];
2938        self.state[dst] = val;
2939        ControlFlow::Continue(())
2940    }
2941
2942    fn vmov(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
2943        let val = self.state[src];
2944        self.state[dst] = val;
2945        ControlFlow::Continue(())
2946    }
2947
2948    fn fconst32(&mut self, dst: FReg, bits: u32) -> ControlFlow<Done> {
2949        self.state[dst].set_f32(f32::from_bits(bits));
2950        ControlFlow::Continue(())
2951    }
2952
2953    fn fconst64(&mut self, dst: FReg, bits: u64) -> ControlFlow<Done> {
2954        self.state[dst].set_f64(f64::from_bits(bits));
2955        ControlFlow::Continue(())
2956    }
2957
2958    fn bitcast_int_from_float_32(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
2959        let val = self.state[src].get_f32();
2960        self.state[dst].set_u32(val.to_bits());
2961        ControlFlow::Continue(())
2962    }
2963
2964    fn bitcast_int_from_float_64(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
2965        let val = self.state[src].get_f64();
2966        self.state[dst].set_u64(val.to_bits());
2967        ControlFlow::Continue(())
2968    }
2969
2970    fn bitcast_float_from_int_32(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
2971        let val = self.state[src].get_u32();
2972        self.state[dst].set_f32(f32::from_bits(val));
2973        ControlFlow::Continue(())
2974    }
2975
2976    fn bitcast_float_from_int_64(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
2977        let val = self.state[src].get_u64();
2978        self.state[dst].set_f64(f64::from_bits(val));
2979        ControlFlow::Continue(())
2980    }
2981
2982    fn feq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
2983        let a = self.state[src1].get_f32();
2984        let b = self.state[src2].get_f32();
2985        self.state[dst].set_u32(u32::from(a == b));
2986        ControlFlow::Continue(())
2987    }
2988
2989    fn fneq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
2990        let a = self.state[src1].get_f32();
2991        let b = self.state[src2].get_f32();
2992        self.state[dst].set_u32(u32::from(a != b));
2993        ControlFlow::Continue(())
2994    }
2995
2996    fn flt32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
2997        let a = self.state[src1].get_f32();
2998        let b = self.state[src2].get_f32();
2999        self.state[dst].set_u32(u32::from(a < b));
3000        ControlFlow::Continue(())
3001    }
3002
3003    fn flteq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3004        let a = self.state[src1].get_f32();
3005        let b = self.state[src2].get_f32();
3006        self.state[dst].set_u32(u32::from(a <= b));
3007        ControlFlow::Continue(())
3008    }
3009
3010    fn feq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3011        let a = self.state[src1].get_f64();
3012        let b = self.state[src2].get_f64();
3013        self.state[dst].set_u32(u32::from(a == b));
3014        ControlFlow::Continue(())
3015    }
3016
3017    fn fneq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3018        let a = self.state[src1].get_f64();
3019        let b = self.state[src2].get_f64();
3020        self.state[dst].set_u32(u32::from(a != b));
3021        ControlFlow::Continue(())
3022    }
3023
3024    fn flt64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3025        let a = self.state[src1].get_f64();
3026        let b = self.state[src2].get_f64();
3027        self.state[dst].set_u32(u32::from(a < b));
3028        ControlFlow::Continue(())
3029    }
3030
3031    fn flteq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3032        let a = self.state[src1].get_f64();
3033        let b = self.state[src2].get_f64();
3034        self.state[dst].set_u32(u32::from(a <= b));
3035        ControlFlow::Continue(())
3036    }
3037
3038    fn fselect32(
3039        &mut self,
3040        dst: FReg,
3041        cond: XReg,
3042        if_nonzero: FReg,
3043        if_zero: FReg,
3044    ) -> ControlFlow<Done> {
3045        let result = if self.state[cond].get_u32() != 0 {
3046            self.state[if_nonzero].get_f32()
3047        } else {
3048            self.state[if_zero].get_f32()
3049        };
3050        self.state[dst].set_f32(result);
3051        ControlFlow::Continue(())
3052    }
3053
3054    fn fselect64(
3055        &mut self,
3056        dst: FReg,
3057        cond: XReg,
3058        if_nonzero: FReg,
3059        if_zero: FReg,
3060    ) -> ControlFlow<Done> {
3061        let result = if self.state[cond].get_u32() != 0 {
3062            self.state[if_nonzero].get_f64()
3063        } else {
3064            self.state[if_zero].get_f64()
3065        };
3066        self.state[dst].set_f64(result);
3067        ControlFlow::Continue(())
3068    }
3069
3070    fn f32_from_x32_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3071        let a = self.state[src].get_i32();
3072        self.state[dst].set_f32(a as f32);
3073        ControlFlow::Continue(())
3074    }
3075
3076    fn f32_from_x32_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3077        let a = self.state[src].get_u32();
3078        self.state[dst].set_f32(a as f32);
3079        ControlFlow::Continue(())
3080    }
3081
3082    fn f32_from_x64_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3083        let a = self.state[src].get_i64();
3084        self.state[dst].set_f32(a as f32);
3085        ControlFlow::Continue(())
3086    }
3087
3088    fn f32_from_x64_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3089        let a = self.state[src].get_u64();
3090        self.state[dst].set_f32(a as f32);
3091        ControlFlow::Continue(())
3092    }
3093
3094    fn f64_from_x32_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3095        let a = self.state[src].get_i32();
3096        self.state[dst].set_f64(a as f64);
3097        ControlFlow::Continue(())
3098    }
3099
3100    fn f64_from_x32_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3101        let a = self.state[src].get_u32();
3102        self.state[dst].set_f64(a as f64);
3103        ControlFlow::Continue(())
3104    }
3105
3106    fn f64_from_x64_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3107        let a = self.state[src].get_i64();
3108        self.state[dst].set_f64(a as f64);
3109        ControlFlow::Continue(())
3110    }
3111
3112    fn f64_from_x64_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3113        let a = self.state[src].get_u64();
3114        self.state[dst].set_f64(a as f64);
3115        ControlFlow::Continue(())
3116    }
3117
3118    fn x32_from_f32_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3119        let a = self.state[src].get_f32();
3120        self.check_xnn_from_fnn::<crate::X32FromF32S>(a.into(), -2147483649.0, 2147483648.0)?;
3121        self.state[dst].set_i32(a as i32);
3122        ControlFlow::Continue(())
3123    }
3124
3125    fn x32_from_f32_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3126        let a = self.state[src].get_f32();
3127        self.check_xnn_from_fnn::<crate::X32FromF32U>(a.into(), -1.0, 4294967296.0)?;
3128        self.state[dst].set_u32(a as u32);
3129        ControlFlow::Continue(())
3130    }
3131
3132    fn x64_from_f32_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3133        let a = self.state[src].get_f32();
3134        self.check_xnn_from_fnn::<crate::X64FromF32S>(
3135            a.into(),
3136            -9223372036854777856.0,
3137            9223372036854775808.0,
3138        )?;
3139        self.state[dst].set_i64(a as i64);
3140        ControlFlow::Continue(())
3141    }
3142
3143    fn x64_from_f32_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3144        let a = self.state[src].get_f32();
3145        self.check_xnn_from_fnn::<crate::X64FromF32U>(a.into(), -1.0, 18446744073709551616.0)?;
3146        self.state[dst].set_u64(a as u64);
3147        ControlFlow::Continue(())
3148    }
3149
3150    fn x32_from_f64_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3151        let a = self.state[src].get_f64();
3152        self.check_xnn_from_fnn::<crate::X32FromF64S>(a, -2147483649.0, 2147483648.0)?;
3153        self.state[dst].set_i32(a as i32);
3154        ControlFlow::Continue(())
3155    }
3156
3157    fn x32_from_f64_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3158        let a = self.state[src].get_f64();
3159        self.check_xnn_from_fnn::<crate::X32FromF64U>(a, -1.0, 4294967296.0)?;
3160        self.state[dst].set_u32(a as u32);
3161        ControlFlow::Continue(())
3162    }
3163
3164    fn x64_from_f64_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3165        let a = self.state[src].get_f64();
3166        self.check_xnn_from_fnn::<crate::X64FromF64S>(
3167            a,
3168            -9223372036854777856.0,
3169            9223372036854775808.0,
3170        )?;
3171        self.state[dst].set_i64(a as i64);
3172        ControlFlow::Continue(())
3173    }
3174
3175    fn x64_from_f64_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3176        let a = self.state[src].get_f64();
3177        self.check_xnn_from_fnn::<crate::X64FromF64U>(a, -1.0, 18446744073709551616.0)?;
3178        self.state[dst].set_u64(a as u64);
3179        ControlFlow::Continue(())
3180    }
3181
3182    fn x32_from_f32_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3183        let a = self.state[src].get_f32();
3184        self.state[dst].set_i32(a as i32);
3185        ControlFlow::Continue(())
3186    }
3187
3188    fn x32_from_f32_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3189        let a = self.state[src].get_f32();
3190        self.state[dst].set_u32(a as u32);
3191        ControlFlow::Continue(())
3192    }
3193
3194    fn x64_from_f32_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3195        let a = self.state[src].get_f32();
3196        self.state[dst].set_i64(a as i64);
3197        ControlFlow::Continue(())
3198    }
3199
3200    fn x64_from_f32_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3201        let a = self.state[src].get_f32();
3202        self.state[dst].set_u64(a as u64);
3203        ControlFlow::Continue(())
3204    }
3205
3206    fn x32_from_f64_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3207        let a = self.state[src].get_f64();
3208        self.state[dst].set_i32(a as i32);
3209        ControlFlow::Continue(())
3210    }
3211
3212    fn x32_from_f64_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3213        let a = self.state[src].get_f64();
3214        self.state[dst].set_u32(a as u32);
3215        ControlFlow::Continue(())
3216    }
3217
3218    fn x64_from_f64_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3219        let a = self.state[src].get_f64();
3220        self.state[dst].set_i64(a as i64);
3221        ControlFlow::Continue(())
3222    }
3223
3224    fn x64_from_f64_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3225        let a = self.state[src].get_f64();
3226        self.state[dst].set_u64(a as u64);
3227        ControlFlow::Continue(())
3228    }
3229
3230    fn f32_from_f64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3231        let a = self.state[src].get_f64();
3232        self.state[dst].set_f32(a as f32);
3233        ControlFlow::Continue(())
3234    }
3235
3236    fn f64_from_f32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3237        let a = self.state[src].get_f32();
3238        self.state[dst].set_f64(a.into());
3239        ControlFlow::Continue(())
3240    }
3241
3242    fn fcopysign32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3243        let a = self.state[operands.src1].get_f32();
3244        let b = self.state[operands.src2].get_f32();
3245        self.state[operands.dst].set_f32(a.wasm_copysign(b));
3246        ControlFlow::Continue(())
3247    }
3248
3249    fn fcopysign64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3250        let a = self.state[operands.src1].get_f64();
3251        let b = self.state[operands.src2].get_f64();
3252        self.state[operands.dst].set_f64(a.wasm_copysign(b));
3253        ControlFlow::Continue(())
3254    }
3255
3256    fn fadd32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3257        let a = self.state[operands.src1].get_f32();
3258        let b = self.state[operands.src2].get_f32();
3259        self.state[operands.dst].set_f32(a + b);
3260        ControlFlow::Continue(())
3261    }
3262
3263    fn fsub32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3264        let a = self.state[operands.src1].get_f32();
3265        let b = self.state[operands.src2].get_f32();
3266        self.state[operands.dst].set_f32(a - b);
3267        ControlFlow::Continue(())
3268    }
3269
3270    fn vsubf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3271        let mut a = self.state[operands.src1].get_f32x4();
3272        let b = self.state[operands.src2].get_f32x4();
3273        for (a, b) in a.iter_mut().zip(b) {
3274            *a = *a - b;
3275        }
3276        self.state[operands.dst].set_f32x4(a);
3277        ControlFlow::Continue(())
3278    }
3279
3280    fn fmul32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3281        let a = self.state[operands.src1].get_f32();
3282        let b = self.state[operands.src2].get_f32();
3283        self.state[operands.dst].set_f32(a * b);
3284        ControlFlow::Continue(())
3285    }
3286
3287    fn vmulf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3288        let mut a = self.state[operands.src1].get_f32x4();
3289        let b = self.state[operands.src2].get_f32x4();
3290        for (a, b) in a.iter_mut().zip(b) {
3291            *a = *a * b;
3292        }
3293        self.state[operands.dst].set_f32x4(a);
3294        ControlFlow::Continue(())
3295    }
3296
3297    fn fdiv32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3298        let a = self.state[operands.src1].get_f32();
3299        let b = self.state[operands.src2].get_f32();
3300        self.state[operands.dst].set_f32(a / b);
3301        ControlFlow::Continue(())
3302    }
3303
3304    fn vdivf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3305        let a = self.state[operands.src1].get_f32x4();
3306        let b = self.state[operands.src2].get_f32x4();
3307        let mut result = [0.0f32; 4];
3308
3309        for i in 0..4 {
3310            result[i] = a[i] / b[i];
3311        }
3312
3313        self.state[operands.dst].set_f32x4(result);
3314        ControlFlow::Continue(())
3315    }
3316
3317    fn vdivf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3318        let a = self.state[operands.src1].get_f64x2();
3319        let b = self.state[operands.src2].get_f64x2();
3320        let mut result = [0.0f64; 2];
3321
3322        for i in 0..2 {
3323            result[i] = a[i] / b[i];
3324        }
3325
3326        self.state[operands.dst].set_f64x2(result);
3327        ControlFlow::Continue(())
3328    }
3329
3330    fn fmaximum32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3331        let a = self.state[operands.src1].get_f32();
3332        let b = self.state[operands.src2].get_f32();
3333        self.state[operands.dst].set_f32(a.wasm_maximum(b));
3334        ControlFlow::Continue(())
3335    }
3336
3337    fn fminimum32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3338        let a = self.state[operands.src1].get_f32();
3339        let b = self.state[operands.src2].get_f32();
3340        self.state[operands.dst].set_f32(a.wasm_minimum(b));
3341        ControlFlow::Continue(())
3342    }
3343
3344    fn ftrunc32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3345        let a = self.state[src].get_f32();
3346        self.state[dst].set_f32(a.wasm_trunc());
3347        ControlFlow::Continue(())
3348    }
3349
3350    fn vtrunc32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3351        let mut a = self.state[src].get_f32x4();
3352        for elem in a.iter_mut() {
3353            *elem = elem.wasm_trunc();
3354        }
3355        self.state[dst].set_f32x4(a);
3356        ControlFlow::Continue(())
3357    }
3358
3359    fn vtrunc64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3360        let mut a = self.state[src].get_f64x2();
3361        for elem in a.iter_mut() {
3362            *elem = elem.wasm_trunc();
3363        }
3364        self.state[dst].set_f64x2(a);
3365        ControlFlow::Continue(())
3366    }
3367
3368    fn ffloor32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3369        let a = self.state[src].get_f32();
3370        self.state[dst].set_f32(a.wasm_floor());
3371        ControlFlow::Continue(())
3372    }
3373
3374    fn vfloor32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3375        let mut a = self.state[src].get_f32x4();
3376        for elem in a.iter_mut() {
3377            *elem = elem.wasm_floor();
3378        }
3379        self.state[dst].set_f32x4(a);
3380        ControlFlow::Continue(())
3381    }
3382
3383    fn vfloor64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3384        let mut a = self.state[src].get_f64x2();
3385        for elem in a.iter_mut() {
3386            *elem = elem.wasm_floor();
3387        }
3388        self.state[dst].set_f64x2(a);
3389        ControlFlow::Continue(())
3390    }
3391
3392    fn fceil32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3393        let a = self.state[src].get_f32();
3394        self.state[dst].set_f32(a.wasm_ceil());
3395        ControlFlow::Continue(())
3396    }
3397
3398    fn vceil32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3399        let mut a = self.state[src].get_f32x4();
3400        for elem in a.iter_mut() {
3401            *elem = elem.wasm_ceil();
3402        }
3403        self.state[dst].set_f32x4(a);
3404
3405        ControlFlow::Continue(())
3406    }
3407
3408    fn vceil64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3409        let mut a = self.state[src].get_f64x2();
3410        for elem in a.iter_mut() {
3411            *elem = elem.wasm_ceil();
3412        }
3413        self.state[dst].set_f64x2(a);
3414
3415        ControlFlow::Continue(())
3416    }
3417
3418    fn fnearest32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3419        let a = self.state[src].get_f32();
3420        self.state[dst].set_f32(a.wasm_nearest());
3421        ControlFlow::Continue(())
3422    }
3423
3424    fn vnearest32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3425        let mut a = self.state[src].get_f32x4();
3426        for elem in a.iter_mut() {
3427            *elem = elem.wasm_nearest();
3428        }
3429        self.state[dst].set_f32x4(a);
3430        ControlFlow::Continue(())
3431    }
3432
3433    fn vnearest64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3434        let mut a = self.state[src].get_f64x2();
3435        for elem in a.iter_mut() {
3436            *elem = elem.wasm_nearest();
3437        }
3438        self.state[dst].set_f64x2(a);
3439        ControlFlow::Continue(())
3440    }
3441
3442    fn fsqrt32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3443        let a = self.state[src].get_f32();
3444        self.state[dst].set_f32(a.wasm_sqrt());
3445        ControlFlow::Continue(())
3446    }
3447
3448    fn vsqrt32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3449        let mut a = self.state[src].get_f32x4();
3450        for elem in a.iter_mut() {
3451            *elem = elem.wasm_sqrt();
3452        }
3453        self.state[dst].set_f32x4(a);
3454        ControlFlow::Continue(())
3455    }
3456
3457    fn vsqrt64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3458        let mut a = self.state[src].get_f64x2();
3459        for elem in a.iter_mut() {
3460            *elem = elem.wasm_sqrt();
3461        }
3462        self.state[dst].set_f64x2(a);
3463        ControlFlow::Continue(())
3464    }
3465
3466    fn fneg32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3467        let a = self.state[src].get_f32();
3468        self.state[dst].set_f32(-a);
3469        ControlFlow::Continue(())
3470    }
3471
3472    fn vnegf32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3473        let mut a = self.state[src].get_f32x4();
3474        for elem in a.iter_mut() {
3475            *elem = -*elem;
3476        }
3477        self.state[dst].set_f32x4(a);
3478        ControlFlow::Continue(())
3479    }
3480
3481    fn fabs32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3482        let a = self.state[src].get_f32();
3483        self.state[dst].set_f32(a.wasm_abs());
3484        ControlFlow::Continue(())
3485    }
3486
3487    fn fadd64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3488        let a = self.state[operands.src1].get_f64();
3489        let b = self.state[operands.src2].get_f64();
3490        self.state[operands.dst].set_f64(a + b);
3491        ControlFlow::Continue(())
3492    }
3493
3494    fn fsub64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3495        let a = self.state[operands.src1].get_f64();
3496        let b = self.state[operands.src2].get_f64();
3497        self.state[operands.dst].set_f64(a - b);
3498        ControlFlow::Continue(())
3499    }
3500
3501    fn fmul64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3502        let a = self.state[operands.src1].get_f64();
3503        let b = self.state[operands.src2].get_f64();
3504        self.state[operands.dst].set_f64(a * b);
3505        ControlFlow::Continue(())
3506    }
3507
3508    fn fdiv64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3509        let a = self.state[operands.src1].get_f64();
3510        let b = self.state[operands.src2].get_f64();
3511        self.state[operands.dst].set_f64(a / b);
3512        ControlFlow::Continue(())
3513    }
3514
3515    fn fmaximum64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3516        let a = self.state[operands.src1].get_f64();
3517        let b = self.state[operands.src2].get_f64();
3518        self.state[operands.dst].set_f64(a.wasm_maximum(b));
3519        ControlFlow::Continue(())
3520    }
3521
3522    fn fminimum64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3523        let a = self.state[operands.src1].get_f64();
3524        let b = self.state[operands.src2].get_f64();
3525        self.state[operands.dst].set_f64(a.wasm_minimum(b));
3526        ControlFlow::Continue(())
3527    }
3528
3529    fn ftrunc64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3530        let a = self.state[src].get_f64();
3531        self.state[dst].set_f64(a.wasm_trunc());
3532        ControlFlow::Continue(())
3533    }
3534
3535    fn ffloor64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3536        let a = self.state[src].get_f64();
3537        self.state[dst].set_f64(a.wasm_floor());
3538        ControlFlow::Continue(())
3539    }
3540
3541    fn fceil64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3542        let a = self.state[src].get_f64();
3543        self.state[dst].set_f64(a.wasm_ceil());
3544        ControlFlow::Continue(())
3545    }
3546
3547    fn fnearest64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3548        let a = self.state[src].get_f64();
3549        self.state[dst].set_f64(a.wasm_nearest());
3550        ControlFlow::Continue(())
3551    }
3552
3553    fn fsqrt64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3554        let a = self.state[src].get_f64();
3555        self.state[dst].set_f64(a.wasm_sqrt());
3556        ControlFlow::Continue(())
3557    }
3558
3559    fn fneg64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3560        let a = self.state[src].get_f64();
3561        self.state[dst].set_f64(-a);
3562        ControlFlow::Continue(())
3563    }
3564
3565    fn fabs64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3566        let a = self.state[src].get_f64();
3567        self.state[dst].set_f64(a.wasm_abs());
3568        ControlFlow::Continue(())
3569    }
3570
3571    fn vaddi8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3572        let mut a = self.state[operands.src1].get_i8x16();
3573        let b = self.state[operands.src2].get_i8x16();
3574        for (a, b) in a.iter_mut().zip(b) {
3575            *a = a.wrapping_add(b);
3576        }
3577        self.state[operands.dst].set_i8x16(a);
3578        ControlFlow::Continue(())
3579    }
3580
3581    fn vaddi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3582        let mut a = self.state[operands.src1].get_i16x8();
3583        let b = self.state[operands.src2].get_i16x8();
3584        for (a, b) in a.iter_mut().zip(b) {
3585            *a = a.wrapping_add(b);
3586        }
3587        self.state[operands.dst].set_i16x8(a);
3588        ControlFlow::Continue(())
3589    }
3590
3591    fn vaddi32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3592        let mut a = self.state[operands.src1].get_i32x4();
3593        let b = self.state[operands.src2].get_i32x4();
3594        for (a, b) in a.iter_mut().zip(b) {
3595            *a = a.wrapping_add(b);
3596        }
3597        self.state[operands.dst].set_i32x4(a);
3598        ControlFlow::Continue(())
3599    }
3600
3601    fn vaddi64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3602        let mut a = self.state[operands.src1].get_i64x2();
3603        let b = self.state[operands.src2].get_i64x2();
3604        for (a, b) in a.iter_mut().zip(b) {
3605            *a = a.wrapping_add(b);
3606        }
3607        self.state[operands.dst].set_i64x2(a);
3608        ControlFlow::Continue(())
3609    }
3610
3611    fn vaddf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3612        let mut a = self.state[operands.src1].get_f32x4();
3613        let b = self.state[operands.src2].get_f32x4();
3614        for (a, b) in a.iter_mut().zip(b) {
3615            *a += b;
3616        }
3617        self.state[operands.dst].set_f32x4(a);
3618        ControlFlow::Continue(())
3619    }
3620
3621    fn vaddf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3622        let mut a = self.state[operands.src1].get_f64x2();
3623        let b = self.state[operands.src2].get_f64x2();
3624        for (a, b) in a.iter_mut().zip(b) {
3625            *a += b;
3626        }
3627        self.state[operands.dst].set_f64x2(a);
3628        ControlFlow::Continue(())
3629    }
3630
3631    fn vaddi8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3632        let mut a = self.state[operands.src1].get_i8x16();
3633        let b = self.state[operands.src2].get_i8x16();
3634        for (a, b) in a.iter_mut().zip(b) {
3635            *a = (*a).saturating_add(b);
3636        }
3637        self.state[operands.dst].set_i8x16(a);
3638        ControlFlow::Continue(())
3639    }
3640
3641    fn vaddu8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3642        let mut a = self.state[operands.src1].get_u8x16();
3643        let b = self.state[operands.src2].get_u8x16();
3644        for (a, b) in a.iter_mut().zip(b) {
3645            *a = (*a).saturating_add(b);
3646        }
3647        self.state[operands.dst].set_u8x16(a);
3648        ControlFlow::Continue(())
3649    }
3650
3651    fn vaddi16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3652        let mut a = self.state[operands.src1].get_i16x8();
3653        let b = self.state[operands.src2].get_i16x8();
3654        for (a, b) in a.iter_mut().zip(b) {
3655            *a = (*a).saturating_add(b);
3656        }
3657        self.state[operands.dst].set_i16x8(a);
3658        ControlFlow::Continue(())
3659    }
3660
3661    fn vaddu16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3662        let mut a = self.state[operands.src1].get_u16x8();
3663        let b = self.state[operands.src2].get_u16x8();
3664        for (a, b) in a.iter_mut().zip(b) {
3665            *a = (*a).saturating_add(b);
3666        }
3667        self.state[operands.dst].set_u16x8(a);
3668        ControlFlow::Continue(())
3669    }
3670
3671    fn vaddpairwisei16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3672        let a = self.state[operands.src1].get_i16x8();
3673        let b = self.state[operands.src2].get_i16x8();
3674        let mut result = [0i16; 8];
3675        let half = result.len() / 2;
3676        for i in 0..half {
3677            result[i] = a[2 * i].wrapping_add(a[2 * i + 1]);
3678            result[i + half] = b[2 * i].wrapping_add(b[2 * i + 1]);
3679        }
3680        self.state[operands.dst].set_i16x8(result);
3681        ControlFlow::Continue(())
3682    }
3683
3684    fn vaddpairwisei32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3685        let a = self.state[operands.src1].get_i32x4();
3686        let b = self.state[operands.src2].get_i32x4();
3687        let mut result = [0i32; 4];
3688        result[0] = a[0].wrapping_add(a[1]);
3689        result[1] = a[2].wrapping_add(a[3]);
3690        result[2] = b[0].wrapping_add(b[1]);
3691        result[3] = b[2].wrapping_add(b[3]);
3692        self.state[operands.dst].set_i32x4(result);
3693        ControlFlow::Continue(())
3694    }
3695
3696    fn vshli8x16(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3697        let a = self.state[operands.src1].get_i8x16();
3698        let b = self.state[operands.src2].get_u32();
3699        self.state[operands.dst].set_i8x16(a.map(|a| a.wrapping_shl(b)));
3700        ControlFlow::Continue(())
3701    }
3702
3703    fn vshli16x8(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3704        let a = self.state[operands.src1].get_i16x8();
3705        let b = self.state[operands.src2].get_u32();
3706        self.state[operands.dst].set_i16x8(a.map(|a| a.wrapping_shl(b)));
3707        ControlFlow::Continue(())
3708    }
3709
3710    fn vshli32x4(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3711        let a = self.state[operands.src1].get_i32x4();
3712        let b = self.state[operands.src2].get_u32();
3713        self.state[operands.dst].set_i32x4(a.map(|a| a.wrapping_shl(b)));
3714        ControlFlow::Continue(())
3715    }
3716
3717    fn vshli64x2(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3718        let a = self.state[operands.src1].get_i64x2();
3719        let b = self.state[operands.src2].get_u32();
3720        self.state[operands.dst].set_i64x2(a.map(|a| a.wrapping_shl(b)));
3721        ControlFlow::Continue(())
3722    }
3723
3724    fn vshri8x16_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3725        let a = self.state[operands.src1].get_i8x16();
3726        let b = self.state[operands.src2].get_u32();
3727        self.state[operands.dst].set_i8x16(a.map(|a| a.wrapping_shr(b)));
3728        ControlFlow::Continue(())
3729    }
3730
3731    fn vshri16x8_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3732        let a = self.state[operands.src1].get_i16x8();
3733        let b = self.state[operands.src2].get_u32();
3734        self.state[operands.dst].set_i16x8(a.map(|a| a.wrapping_shr(b)));
3735        ControlFlow::Continue(())
3736    }
3737
3738    fn vshri32x4_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3739        let a = self.state[operands.src1].get_i32x4();
3740        let b = self.state[operands.src2].get_u32();
3741        self.state[operands.dst].set_i32x4(a.map(|a| a.wrapping_shr(b)));
3742        ControlFlow::Continue(())
3743    }
3744
3745    fn vshri64x2_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3746        let a = self.state[operands.src1].get_i64x2();
3747        let b = self.state[operands.src2].get_u32();
3748        self.state[operands.dst].set_i64x2(a.map(|a| a.wrapping_shr(b)));
3749        ControlFlow::Continue(())
3750    }
3751
3752    fn vshri8x16_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3753        let a = self.state[operands.src1].get_u8x16();
3754        let b = self.state[operands.src2].get_u32();
3755        self.state[operands.dst].set_u8x16(a.map(|a| a.wrapping_shr(b)));
3756        ControlFlow::Continue(())
3757    }
3758
3759    fn vshri16x8_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3760        let a = self.state[operands.src1].get_u16x8();
3761        let b = self.state[operands.src2].get_u32();
3762        self.state[operands.dst].set_u16x8(a.map(|a| a.wrapping_shr(b)));
3763        ControlFlow::Continue(())
3764    }
3765
3766    fn vshri32x4_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3767        let a = self.state[operands.src1].get_u32x4();
3768        let b = self.state[operands.src2].get_u32();
3769        self.state[operands.dst].set_u32x4(a.map(|a| a.wrapping_shr(b)));
3770        ControlFlow::Continue(())
3771    }
3772
3773    fn vshri64x2_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3774        let a = self.state[operands.src1].get_u64x2();
3775        let b = self.state[operands.src2].get_u32();
3776        self.state[operands.dst].set_u64x2(a.map(|a| a.wrapping_shr(b)));
3777        ControlFlow::Continue(())
3778    }
3779
3780    fn vconst128(&mut self, dst: VReg, val: u128) -> ControlFlow<Done> {
3781        self.state[dst].set_u128(val);
3782        ControlFlow::Continue(())
3783    }
3784
3785    fn vsplatx8(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
3786        let val = self.state[src].get_u32() as u8;
3787        self.state[dst].set_u8x16([val; 16]);
3788        ControlFlow::Continue(())
3789    }
3790
3791    fn vsplatx16(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
3792        let val = self.state[src].get_u32() as u16;
3793        self.state[dst].set_u16x8([val; 8]);
3794        ControlFlow::Continue(())
3795    }
3796
3797    fn vsplatx32(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
3798        let val = self.state[src].get_u32();
3799        self.state[dst].set_u32x4([val; 4]);
3800        ControlFlow::Continue(())
3801    }
3802
3803    fn vsplatx64(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
3804        let val = self.state[src].get_u64();
3805        self.state[dst].set_u64x2([val; 2]);
3806        ControlFlow::Continue(())
3807    }
3808
3809    fn vsplatf32(&mut self, dst: VReg, src: FReg) -> ControlFlow<Done> {
3810        let val = self.state[src].get_f32();
3811        self.state[dst].set_f32x4([val; 4]);
3812        ControlFlow::Continue(())
3813    }
3814
3815    fn vsplatf64(&mut self, dst: VReg, src: FReg) -> ControlFlow<Done> {
3816        let val = self.state[src].get_f64();
3817        self.state[dst].set_f64x2([val; 2]);
3818        ControlFlow::Continue(())
3819    }
3820
3821    fn vload8x8_s_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3822        let val = unsafe { self.load::<[i8; 8]>(ptr, offset) };
3823        self.state[dst].set_i16x8(val.map(|i| i.into()));
3824        ControlFlow::Continue(())
3825    }
3826
3827    fn vload8x8_u_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3828        let val = unsafe { self.load::<[u8; 8]>(ptr, offset) };
3829        self.state[dst].set_u16x8(val.map(|i| i.into()));
3830        ControlFlow::Continue(())
3831    }
3832
3833    fn vload16x4le_s_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3834        let val = unsafe { self.load::<[i16; 4]>(ptr, offset) };
3835        self.state[dst].set_i32x4(val.map(|i| i16::from_le(i).into()));
3836        ControlFlow::Continue(())
3837    }
3838
3839    fn vload16x4le_u_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3840        let val = unsafe { self.load::<[u16; 4]>(ptr, offset) };
3841        self.state[dst].set_u32x4(val.map(|i| u16::from_le(i).into()));
3842        ControlFlow::Continue(())
3843    }
3844
3845    fn vload32x2le_s_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3846        let val = unsafe { self.load::<[i32; 2]>(ptr, offset) };
3847        self.state[dst].set_i64x2(val.map(|i| i32::from_le(i).into()));
3848        ControlFlow::Continue(())
3849    }
3850
3851    fn vload32x2le_u_offset32(&mut self, dst: VReg, ptr: XReg, offset: i32) -> ControlFlow<Done> {
3852        let val = unsafe { self.load::<[u32; 2]>(ptr, offset) };
3853        self.state[dst].set_u64x2(val.map(|i| u32::from_le(i).into()));
3854        ControlFlow::Continue(())
3855    }
3856
3857    fn vband128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3858        let a = self.state[operands.src1].get_u128();
3859        let b = self.state[operands.src2].get_u128();
3860        self.state[operands.dst].set_u128(a & b);
3861        ControlFlow::Continue(())
3862    }
3863
3864    fn vbor128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3865        let a = self.state[operands.src1].get_u128();
3866        let b = self.state[operands.src2].get_u128();
3867        self.state[operands.dst].set_u128(a | b);
3868        ControlFlow::Continue(())
3869    }
3870
3871    fn vbxor128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3872        let a = self.state[operands.src1].get_u128();
3873        let b = self.state[operands.src2].get_u128();
3874        self.state[operands.dst].set_u128(a ^ b);
3875        ControlFlow::Continue(())
3876    }
3877
3878    fn vbnot128(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3879        let a = self.state[src].get_u128();
3880        self.state[dst].set_u128(!a);
3881        ControlFlow::Continue(())
3882    }
3883
3884    fn vbitselect128(&mut self, dst: VReg, c: VReg, x: VReg, y: VReg) -> ControlFlow<Done> {
3885        let c = self.state[c].get_u128();
3886        let x = self.state[x].get_u128();
3887        let y = self.state[y].get_u128();
3888        self.state[dst].set_u128((c & x) | (!c & y));
3889        ControlFlow::Continue(())
3890    }
3891
3892    fn vbitmask8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3893        let a = self.state[src].get_u8x16();
3894        let mut result = 0;
3895        for item in a.iter().rev() {
3896            result <<= 1;
3897            result |= (*item >> 7) as u32;
3898        }
3899        self.state[dst].set_u32(result);
3900        ControlFlow::Continue(())
3901    }
3902
3903    fn vbitmask16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3904        let a = self.state[src].get_u16x8();
3905        let mut result = 0;
3906        for item in a.iter().rev() {
3907            result <<= 1;
3908            result |= (*item >> 15) as u32;
3909        }
3910        self.state[dst].set_u32(result);
3911        ControlFlow::Continue(())
3912    }
3913
3914    fn vbitmask32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3915        let a = self.state[src].get_u32x4();
3916        let mut result = 0;
3917        for item in a.iter().rev() {
3918            result <<= 1;
3919            result |= *item >> 31;
3920        }
3921        self.state[dst].set_u32(result);
3922        ControlFlow::Continue(())
3923    }
3924
3925    fn vbitmask64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3926        let a = self.state[src].get_u64x2();
3927        let mut result = 0;
3928        for item in a.iter().rev() {
3929            result <<= 1;
3930            result |= (*item >> 63) as u32;
3931        }
3932        self.state[dst].set_u32(result);
3933        ControlFlow::Continue(())
3934    }
3935
3936    fn valltrue8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3937        let a = self.state[src].get_u8x16();
3938        let result = a.iter().all(|a| *a != 0);
3939        self.state[dst].set_u32(u32::from(result));
3940        ControlFlow::Continue(())
3941    }
3942
3943    fn valltrue16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3944        let a = self.state[src].get_u16x8();
3945        let result = a.iter().all(|a| *a != 0);
3946        self.state[dst].set_u32(u32::from(result));
3947        ControlFlow::Continue(())
3948    }
3949
3950    fn valltrue32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3951        let a = self.state[src].get_u32x4();
3952        let result = a.iter().all(|a| *a != 0);
3953        self.state[dst].set_u32(u32::from(result));
3954        ControlFlow::Continue(())
3955    }
3956
3957    fn valltrue64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3958        let a = self.state[src].get_u64x2();
3959        let result = a.iter().all(|a| *a != 0);
3960        self.state[dst].set_u32(u32::from(result));
3961        ControlFlow::Continue(())
3962    }
3963
3964    fn vanytrue8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3965        let a = self.state[src].get_u8x16();
3966        let result = a.iter().any(|a| *a != 0);
3967        self.state[dst].set_u32(u32::from(result));
3968        ControlFlow::Continue(())
3969    }
3970
3971    fn vanytrue16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3972        let a = self.state[src].get_u16x8();
3973        let result = a.iter().any(|a| *a != 0);
3974        self.state[dst].set_u32(u32::from(result));
3975        ControlFlow::Continue(())
3976    }
3977
3978    fn vanytrue32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3979        let a = self.state[src].get_u32x4();
3980        let result = a.iter().any(|a| *a != 0);
3981        self.state[dst].set_u32(u32::from(result));
3982        ControlFlow::Continue(())
3983    }
3984
3985    fn vanytrue64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
3986        let a = self.state[src].get_u64x2();
3987        let result = a.iter().any(|a| *a != 0);
3988        self.state[dst].set_u32(u32::from(result));
3989        ControlFlow::Continue(())
3990    }
3991
3992    fn vf32x4_from_i32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3993        let a = self.state[src].get_i32x4();
3994        self.state[dst].set_f32x4(a.map(|i| i as f32));
3995        ControlFlow::Continue(())
3996    }
3997
3998    fn vf32x4_from_i32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3999        let a = self.state[src].get_u32x4();
4000        self.state[dst].set_f32x4(a.map(|i| i as f32));
4001        ControlFlow::Continue(())
4002    }
4003
4004    fn vf64x2_from_i64x2_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4005        let a = self.state[src].get_i64x2();
4006        self.state[dst].set_f64x2(a.map(|i| i as f64));
4007        ControlFlow::Continue(())
4008    }
4009
4010    fn vf64x2_from_i64x2_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4011        let a = self.state[src].get_u64x2();
4012        self.state[dst].set_f64x2(a.map(|i| i as f64));
4013        ControlFlow::Continue(())
4014    }
4015
4016    fn vi32x4_from_f32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4017        let a = self.state[src].get_f32x4();
4018        self.state[dst].set_i32x4(a.map(|f| f as i32));
4019        ControlFlow::Continue(())
4020    }
4021
4022    fn vi32x4_from_f32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4023        let a = self.state[src].get_f32x4();
4024        self.state[dst].set_u32x4(a.map(|f| f as u32));
4025        ControlFlow::Continue(())
4026    }
4027
4028    fn vi64x2_from_f64x2_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4029        let a = self.state[src].get_f64x2();
4030        self.state[dst].set_i64x2(a.map(|f| f as i64));
4031        ControlFlow::Continue(())
4032    }
4033
4034    fn vi64x2_from_f64x2_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4035        let a = self.state[src].get_f64x2();
4036        self.state[dst].set_u64x2(a.map(|f| f as u64));
4037        ControlFlow::Continue(())
4038    }
4039
4040    fn vwidenlow8x16_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4041        let a = *self.state[src].get_i8x16().first_chunk().unwrap();
4042        self.state[dst].set_i16x8(a.map(|i| i.into()));
4043        ControlFlow::Continue(())
4044    }
4045
4046    fn vwidenlow8x16_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4047        let a = *self.state[src].get_u8x16().first_chunk().unwrap();
4048        self.state[dst].set_u16x8(a.map(|i| i.into()));
4049        ControlFlow::Continue(())
4050    }
4051
4052    fn vwidenlow16x8_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4053        let a = *self.state[src].get_i16x8().first_chunk().unwrap();
4054        self.state[dst].set_i32x4(a.map(|i| i.into()));
4055        ControlFlow::Continue(())
4056    }
4057
4058    fn vwidenlow16x8_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4059        let a = *self.state[src].get_u16x8().first_chunk().unwrap();
4060        self.state[dst].set_u32x4(a.map(|i| i.into()));
4061        ControlFlow::Continue(())
4062    }
4063
4064    fn vwidenlow32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4065        let a = *self.state[src].get_i32x4().first_chunk().unwrap();
4066        self.state[dst].set_i64x2(a.map(|i| i.into()));
4067        ControlFlow::Continue(())
4068    }
4069
4070    fn vwidenlow32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4071        let a = *self.state[src].get_u32x4().first_chunk().unwrap();
4072        self.state[dst].set_u64x2(a.map(|i| i.into()));
4073        ControlFlow::Continue(())
4074    }
4075
4076    fn vwidenhigh8x16_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4077        let a = *self.state[src].get_i8x16().last_chunk().unwrap();
4078        self.state[dst].set_i16x8(a.map(|i| i.into()));
4079        ControlFlow::Continue(())
4080    }
4081
4082    fn vwidenhigh8x16_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4083        let a = *self.state[src].get_u8x16().last_chunk().unwrap();
4084        self.state[dst].set_u16x8(a.map(|i| i.into()));
4085        ControlFlow::Continue(())
4086    }
4087
4088    fn vwidenhigh16x8_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4089        let a = *self.state[src].get_i16x8().last_chunk().unwrap();
4090        self.state[dst].set_i32x4(a.map(|i| i.into()));
4091        ControlFlow::Continue(())
4092    }
4093
4094    fn vwidenhigh16x8_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4095        let a = *self.state[src].get_u16x8().last_chunk().unwrap();
4096        self.state[dst].set_u32x4(a.map(|i| i.into()));
4097        ControlFlow::Continue(())
4098    }
4099
4100    fn vwidenhigh32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4101        let a = *self.state[src].get_i32x4().last_chunk().unwrap();
4102        self.state[dst].set_i64x2(a.map(|i| i.into()));
4103        ControlFlow::Continue(())
4104    }
4105
4106    fn vwidenhigh32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4107        let a = *self.state[src].get_u32x4().last_chunk().unwrap();
4108        self.state[dst].set_u64x2(a.map(|i| i.into()));
4109        ControlFlow::Continue(())
4110    }
4111
4112    fn vnarrow16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4113        let a = self.state[operands.src1].get_i16x8();
4114        let b = self.state[operands.src2].get_i16x8();
4115        let mut result = [0; 16];
4116        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4117            *d = (*i)
4118                .try_into()
4119                .unwrap_or(if *i < 0 { i8::MIN } else { i8::MAX });
4120        }
4121        self.state[operands.dst].set_i8x16(result);
4122        ControlFlow::Continue(())
4123    }
4124
4125    fn vnarrow16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4126        let a = self.state[operands.src1].get_i16x8();
4127        let b = self.state[operands.src2].get_i16x8();
4128        let mut result = [0; 16];
4129        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4130            *d = (*i)
4131                .try_into()
4132                .unwrap_or(if *i < 0 { u8::MIN } else { u8::MAX });
4133        }
4134        self.state[operands.dst].set_u8x16(result);
4135        ControlFlow::Continue(())
4136    }
4137
4138    fn vnarrow32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4139        let a = self.state[operands.src1].get_i32x4();
4140        let b = self.state[operands.src2].get_i32x4();
4141        let mut result = [0; 8];
4142        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4143            *d = (*i)
4144                .try_into()
4145                .unwrap_or(if *i < 0 { i16::MIN } else { i16::MAX });
4146        }
4147        self.state[operands.dst].set_i16x8(result);
4148        ControlFlow::Continue(())
4149    }
4150
4151    fn vnarrow32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4152        let a = self.state[operands.src1].get_i32x4();
4153        let b = self.state[operands.src2].get_i32x4();
4154        let mut result = [0; 8];
4155        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4156            *d = (*i)
4157                .try_into()
4158                .unwrap_or(if *i < 0 { u16::MIN } else { u16::MAX });
4159        }
4160        self.state[operands.dst].set_u16x8(result);
4161        ControlFlow::Continue(())
4162    }
4163
4164    fn vnarrow64x2_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4165        let a = self.state[operands.src1].get_i64x2();
4166        let b = self.state[operands.src2].get_i64x2();
4167        let mut result = [0; 4];
4168        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4169            *d = (*i)
4170                .try_into()
4171                .unwrap_or(if *i < 0 { i32::MIN } else { i32::MAX });
4172        }
4173        self.state[operands.dst].set_i32x4(result);
4174        ControlFlow::Continue(())
4175    }
4176
4177    fn vnarrow64x2_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4178        let a = self.state[operands.src1].get_i64x2();
4179        let b = self.state[operands.src2].get_i64x2();
4180        let mut result = [0; 4];
4181        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4182            *d = (*i)
4183                .try_into()
4184                .unwrap_or(if *i < 0 { u32::MIN } else { u32::MAX });
4185        }
4186        self.state[operands.dst].set_u32x4(result);
4187        ControlFlow::Continue(())
4188    }
4189
4190    fn vunarrow64x2_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4191        let a = self.state[operands.src1].get_u64x2();
4192        let b = self.state[operands.src2].get_u64x2();
4193        let mut result = [0; 4];
4194        for (i, d) in a.iter().chain(&b).zip(&mut result) {
4195            *d = (*i).try_into().unwrap_or(u32::MAX);
4196        }
4197        self.state[operands.dst].set_u32x4(result);
4198        ControlFlow::Continue(())
4199    }
4200
4201    fn vfpromotelow(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4202        let a = self.state[src].get_f32x4();
4203        self.state[dst].set_f64x2([a[0].into(), a[1].into()]);
4204        ControlFlow::Continue(())
4205    }
4206
4207    fn vfdemote(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4208        let a = self.state[src].get_f64x2();
4209        self.state[dst].set_f32x4([a[0] as f32, a[1] as f32, 0.0, 0.0]);
4210        ControlFlow::Continue(())
4211    }
4212
4213    fn vsubi8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4214        let mut a = self.state[operands.src1].get_i8x16();
4215        let b = self.state[operands.src2].get_i8x16();
4216        for (a, b) in a.iter_mut().zip(b) {
4217            *a = a.wrapping_sub(b);
4218        }
4219        self.state[operands.dst].set_i8x16(a);
4220        ControlFlow::Continue(())
4221    }
4222
4223    fn vsubi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4224        let mut a = self.state[operands.src1].get_i16x8();
4225        let b = self.state[operands.src2].get_i16x8();
4226        for (a, b) in a.iter_mut().zip(b) {
4227            *a = a.wrapping_sub(b);
4228        }
4229        self.state[operands.dst].set_i16x8(a);
4230        ControlFlow::Continue(())
4231    }
4232
4233    fn vsubi32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4234        let mut a = self.state[operands.src1].get_i32x4();
4235        let b = self.state[operands.src2].get_i32x4();
4236        for (a, b) in a.iter_mut().zip(b) {
4237            *a = a.wrapping_sub(b);
4238        }
4239        self.state[operands.dst].set_i32x4(a);
4240        ControlFlow::Continue(())
4241    }
4242
4243    fn vsubi64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4244        let mut a = self.state[operands.src1].get_i64x2();
4245        let b = self.state[operands.src2].get_i64x2();
4246        for (a, b) in a.iter_mut().zip(b) {
4247            *a = a.wrapping_sub(b);
4248        }
4249        self.state[operands.dst].set_i64x2(a);
4250        ControlFlow::Continue(())
4251    }
4252
4253    fn vsubi8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4254        let mut a = self.state[operands.src1].get_i8x16();
4255        let b = self.state[operands.src2].get_i8x16();
4256        for (a, b) in a.iter_mut().zip(b) {
4257            *a = a.saturating_sub(b);
4258        }
4259        self.state[operands.dst].set_i8x16(a);
4260        ControlFlow::Continue(())
4261    }
4262
4263    fn vsubu8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4264        let mut a = self.state[operands.src1].get_u8x16();
4265        let b = self.state[operands.src2].get_u8x16();
4266        for (a, b) in a.iter_mut().zip(b) {
4267            *a = a.saturating_sub(b);
4268        }
4269        self.state[operands.dst].set_u8x16(a);
4270        ControlFlow::Continue(())
4271    }
4272
4273    fn vsubi16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4274        let mut a = self.state[operands.src1].get_i16x8();
4275        let b = self.state[operands.src2].get_i16x8();
4276        for (a, b) in a.iter_mut().zip(b) {
4277            *a = a.saturating_sub(b);
4278        }
4279        self.state[operands.dst].set_i16x8(a);
4280        ControlFlow::Continue(())
4281    }
4282
4283    fn vsubu16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4284        let mut a = self.state[operands.src1].get_u16x8();
4285        let b = self.state[operands.src2].get_u16x8();
4286        for (a, b) in a.iter_mut().zip(b) {
4287            *a = a.saturating_sub(b);
4288        }
4289        self.state[operands.dst].set_u16x8(a);
4290        ControlFlow::Continue(())
4291    }
4292
4293    fn vsubf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4294        let mut a = self.state[operands.src1].get_f64x2();
4295        let b = self.state[operands.src2].get_f64x2();
4296        for (a, b) in a.iter_mut().zip(b) {
4297            *a = *a - b;
4298        }
4299        self.state[operands.dst].set_f64x2(a);
4300        ControlFlow::Continue(())
4301    }
4302
4303    fn vmuli8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4304        let mut a = self.state[operands.src1].get_i8x16();
4305        let b = self.state[operands.src2].get_i8x16();
4306        for (a, b) in a.iter_mut().zip(b) {
4307            *a = a.wrapping_mul(b);
4308        }
4309        self.state[operands.dst].set_i8x16(a);
4310        ControlFlow::Continue(())
4311    }
4312
4313    fn vmuli16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4314        let mut a = self.state[operands.src1].get_i16x8();
4315        let b = self.state[operands.src2].get_i16x8();
4316        for (a, b) in a.iter_mut().zip(b) {
4317            *a = a.wrapping_mul(b);
4318        }
4319        self.state[operands.dst].set_i16x8(a);
4320        ControlFlow::Continue(())
4321    }
4322
4323    fn vmuli32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4324        let mut a = self.state[operands.src1].get_i32x4();
4325        let b = self.state[operands.src2].get_i32x4();
4326        for (a, b) in a.iter_mut().zip(b) {
4327            *a = a.wrapping_mul(b);
4328        }
4329        self.state[operands.dst].set_i32x4(a);
4330        ControlFlow::Continue(())
4331    }
4332
4333    fn vmuli64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4334        let mut a = self.state[operands.src1].get_i64x2();
4335        let b = self.state[operands.src2].get_i64x2();
4336        for (a, b) in a.iter_mut().zip(b) {
4337            *a = a.wrapping_mul(b);
4338        }
4339        self.state[operands.dst].set_i64x2(a);
4340        ControlFlow::Continue(())
4341    }
4342
4343    fn vmulf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4344        let mut a = self.state[operands.src1].get_f64x2();
4345        let b = self.state[operands.src2].get_f64x2();
4346        for (a, b) in a.iter_mut().zip(b) {
4347            *a = *a * b;
4348        }
4349        self.state[operands.dst].set_f64x2(a);
4350        ControlFlow::Continue(())
4351    }
4352
4353    fn vqmulrsi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4354        let mut a = self.state[operands.src1].get_i16x8();
4355        let b = self.state[operands.src2].get_i16x8();
4356        const MIN: i32 = i16::MIN as i32;
4357        const MAX: i32 = i16::MAX as i32;
4358        for (a, b) in a.iter_mut().zip(b) {
4359            let r = (i32::from(*a) * i32::from(b) + (1 << 14)) >> 15;
4360            *a = r.clamp(MIN, MAX) as i16;
4361        }
4362        self.state[operands.dst].set_i16x8(a);
4363        ControlFlow::Continue(())
4364    }
4365
4366    fn vpopcnt8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4367        let a = self.state[src].get_u8x16();
4368        self.state[dst].set_u8x16(a.map(|i| i.count_ones() as u8));
4369        ControlFlow::Continue(())
4370    }
4371
4372    fn xextractv8x16(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4373        let a = unsafe { *self.state[src].get_u8x16().get_unchecked(usize::from(lane)) };
4374        self.state[dst].set_u32(u32::from(a));
4375        ControlFlow::Continue(())
4376    }
4377
4378    fn xextractv16x8(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4379        let a = unsafe { *self.state[src].get_u16x8().get_unchecked(usize::from(lane)) };
4380        self.state[dst].set_u32(u32::from(a));
4381        ControlFlow::Continue(())
4382    }
4383
4384    fn xextractv32x4(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4385        let a = unsafe { *self.state[src].get_u32x4().get_unchecked(usize::from(lane)) };
4386        self.state[dst].set_u32(a);
4387        ControlFlow::Continue(())
4388    }
4389
4390    fn xextractv64x2(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4391        let a = unsafe { *self.state[src].get_u64x2().get_unchecked(usize::from(lane)) };
4392        self.state[dst].set_u64(a);
4393        ControlFlow::Continue(())
4394    }
4395
4396    fn fextractv32x4(&mut self, dst: FReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4397        let a = unsafe { *self.state[src].get_f32x4().get_unchecked(usize::from(lane)) };
4398        self.state[dst].set_f32(a);
4399        ControlFlow::Continue(())
4400    }
4401
4402    fn fextractv64x2(&mut self, dst: FReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4403        let a = unsafe { *self.state[src].get_f64x2().get_unchecked(usize::from(lane)) };
4404        self.state[dst].set_f64(a);
4405        ControlFlow::Continue(())
4406    }
4407
4408    fn vinsertx8(
4409        &mut self,
4410        operands: BinaryOperands<VReg, VReg, XReg>,
4411        lane: u8,
4412    ) -> ControlFlow<Done> {
4413        let mut a = self.state[operands.src1].get_u8x16();
4414        let b = self.state[operands.src2].get_u32() as u8;
4415        unsafe {
4416            *a.get_unchecked_mut(usize::from(lane)) = b;
4417        }
4418        self.state[operands.dst].set_u8x16(a);
4419        ControlFlow::Continue(())
4420    }
4421
4422    fn vinsertx16(
4423        &mut self,
4424        operands: BinaryOperands<VReg, VReg, XReg>,
4425        lane: u8,
4426    ) -> ControlFlow<Done> {
4427        let mut a = self.state[operands.src1].get_u16x8();
4428        let b = self.state[operands.src2].get_u32() as u16;
4429        unsafe {
4430            *a.get_unchecked_mut(usize::from(lane)) = b;
4431        }
4432        self.state[operands.dst].set_u16x8(a);
4433        ControlFlow::Continue(())
4434    }
4435
4436    fn vinsertx32(
4437        &mut self,
4438        operands: BinaryOperands<VReg, VReg, XReg>,
4439        lane: u8,
4440    ) -> ControlFlow<Done> {
4441        let mut a = self.state[operands.src1].get_u32x4();
4442        let b = self.state[operands.src2].get_u32();
4443        unsafe {
4444            *a.get_unchecked_mut(usize::from(lane)) = b;
4445        }
4446        self.state[operands.dst].set_u32x4(a);
4447        ControlFlow::Continue(())
4448    }
4449
4450    fn vinsertx64(
4451        &mut self,
4452        operands: BinaryOperands<VReg, VReg, XReg>,
4453        lane: u8,
4454    ) -> ControlFlow<Done> {
4455        let mut a = self.state[operands.src1].get_u64x2();
4456        let b = self.state[operands.src2].get_u64();
4457        unsafe {
4458            *a.get_unchecked_mut(usize::from(lane)) = b;
4459        }
4460        self.state[operands.dst].set_u64x2(a);
4461        ControlFlow::Continue(())
4462    }
4463
4464    fn vinsertf32(
4465        &mut self,
4466        operands: BinaryOperands<VReg, VReg, FReg>,
4467        lane: u8,
4468    ) -> ControlFlow<Done> {
4469        let mut a = self.state[operands.src1].get_f32x4();
4470        let b = self.state[operands.src2].get_f32();
4471        unsafe {
4472            *a.get_unchecked_mut(usize::from(lane)) = b;
4473        }
4474        self.state[operands.dst].set_f32x4(a);
4475        ControlFlow::Continue(())
4476    }
4477
4478    fn vinsertf64(
4479        &mut self,
4480        operands: BinaryOperands<VReg, VReg, FReg>,
4481        lane: u8,
4482    ) -> ControlFlow<Done> {
4483        let mut a = self.state[operands.src1].get_f64x2();
4484        let b = self.state[operands.src2].get_f64();
4485        unsafe {
4486            *a.get_unchecked_mut(usize::from(lane)) = b;
4487        }
4488        self.state[operands.dst].set_f64x2(a);
4489        ControlFlow::Continue(())
4490    }
4491
4492    fn veq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4493        let a = self.state[operands.src1].get_u8x16();
4494        let b = self.state[operands.src2].get_u8x16();
4495        let mut c = [0; 16];
4496        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4497            *c = if a == b { u8::MAX } else { 0 };
4498        }
4499        self.state[operands.dst].set_u8x16(c);
4500        ControlFlow::Continue(())
4501    }
4502
4503    fn vneq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4504        let a = self.state[operands.src1].get_u8x16();
4505        let b = self.state[operands.src2].get_u8x16();
4506        let mut c = [0; 16];
4507        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4508            *c = if a != b { u8::MAX } else { 0 };
4509        }
4510        self.state[operands.dst].set_u8x16(c);
4511        ControlFlow::Continue(())
4512    }
4513
4514    fn vslt8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4515        let a = self.state[operands.src1].get_i8x16();
4516        let b = self.state[operands.src2].get_i8x16();
4517        let mut c = [0; 16];
4518        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4519            *c = if a < b { u8::MAX } else { 0 };
4520        }
4521        self.state[operands.dst].set_u8x16(c);
4522        ControlFlow::Continue(())
4523    }
4524
4525    fn vslteq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4526        let a = self.state[operands.src1].get_i8x16();
4527        let b = self.state[operands.src2].get_i8x16();
4528        let mut c = [0; 16];
4529        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4530            *c = if a <= b { u8::MAX } else { 0 };
4531        }
4532        self.state[operands.dst].set_u8x16(c);
4533        ControlFlow::Continue(())
4534    }
4535
4536    fn vult8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4537        let a = self.state[operands.src1].get_u8x16();
4538        let b = self.state[operands.src2].get_u8x16();
4539        let mut c = [0; 16];
4540        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4541            *c = if a < b { u8::MAX } else { 0 };
4542        }
4543        self.state[operands.dst].set_u8x16(c);
4544        ControlFlow::Continue(())
4545    }
4546
4547    fn vulteq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4548        let a = self.state[operands.src1].get_u8x16();
4549        let b = self.state[operands.src2].get_u8x16();
4550        let mut c = [0; 16];
4551        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4552            *c = if a <= b { u8::MAX } else { 0 };
4553        }
4554        self.state[operands.dst].set_u8x16(c);
4555        ControlFlow::Continue(())
4556    }
4557
4558    fn veq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4559        let a = self.state[operands.src1].get_u16x8();
4560        let b = self.state[operands.src2].get_u16x8();
4561        let mut c = [0; 8];
4562        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4563            *c = if a == b { u16::MAX } else { 0 };
4564        }
4565        self.state[operands.dst].set_u16x8(c);
4566        ControlFlow::Continue(())
4567    }
4568
4569    fn vneq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4570        let a = self.state[operands.src1].get_u16x8();
4571        let b = self.state[operands.src2].get_u16x8();
4572        let mut c = [0; 8];
4573        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4574            *c = if a != b { u16::MAX } else { 0 };
4575        }
4576        self.state[operands.dst].set_u16x8(c);
4577        ControlFlow::Continue(())
4578    }
4579
4580    fn vslt16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4581        let a = self.state[operands.src1].get_i16x8();
4582        let b = self.state[operands.src2].get_i16x8();
4583        let mut c = [0; 8];
4584        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4585            *c = if a < b { u16::MAX } else { 0 };
4586        }
4587        self.state[operands.dst].set_u16x8(c);
4588        ControlFlow::Continue(())
4589    }
4590
4591    fn vslteq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4592        let a = self.state[operands.src1].get_i16x8();
4593        let b = self.state[operands.src2].get_i16x8();
4594        let mut c = [0; 8];
4595        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4596            *c = if a <= b { u16::MAX } else { 0 };
4597        }
4598        self.state[operands.dst].set_u16x8(c);
4599        ControlFlow::Continue(())
4600    }
4601
4602    fn vult16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4603        let a = self.state[operands.src1].get_u16x8();
4604        let b = self.state[operands.src2].get_u16x8();
4605        let mut c = [0; 8];
4606        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4607            *c = if a < b { u16::MAX } else { 0 };
4608        }
4609        self.state[operands.dst].set_u16x8(c);
4610        ControlFlow::Continue(())
4611    }
4612
4613    fn vulteq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4614        let a = self.state[operands.src1].get_u16x8();
4615        let b = self.state[operands.src2].get_u16x8();
4616        let mut c = [0; 8];
4617        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4618            *c = if a <= b { u16::MAX } else { 0 };
4619        }
4620        self.state[operands.dst].set_u16x8(c);
4621        ControlFlow::Continue(())
4622    }
4623
4624    fn veq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4625        let a = self.state[operands.src1].get_u32x4();
4626        let b = self.state[operands.src2].get_u32x4();
4627        let mut c = [0; 4];
4628        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4629            *c = if a == b { u32::MAX } else { 0 };
4630        }
4631        self.state[operands.dst].set_u32x4(c);
4632        ControlFlow::Continue(())
4633    }
4634
4635    fn vneq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4636        let a = self.state[operands.src1].get_u32x4();
4637        let b = self.state[operands.src2].get_u32x4();
4638        let mut c = [0; 4];
4639        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4640            *c = if a != b { u32::MAX } else { 0 };
4641        }
4642        self.state[operands.dst].set_u32x4(c);
4643        ControlFlow::Continue(())
4644    }
4645
4646    fn vslt32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4647        let a = self.state[operands.src1].get_i32x4();
4648        let b = self.state[operands.src2].get_i32x4();
4649        let mut c = [0; 4];
4650        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4651            *c = if a < b { u32::MAX } else { 0 };
4652        }
4653        self.state[operands.dst].set_u32x4(c);
4654        ControlFlow::Continue(())
4655    }
4656
4657    fn vslteq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4658        let a = self.state[operands.src1].get_i32x4();
4659        let b = self.state[operands.src2].get_i32x4();
4660        let mut c = [0; 4];
4661        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4662            *c = if a <= b { u32::MAX } else { 0 };
4663        }
4664        self.state[operands.dst].set_u32x4(c);
4665        ControlFlow::Continue(())
4666    }
4667
4668    fn vult32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4669        let a = self.state[operands.src1].get_u32x4();
4670        let b = self.state[operands.src2].get_u32x4();
4671        let mut c = [0; 4];
4672        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4673            *c = if a < b { u32::MAX } else { 0 };
4674        }
4675        self.state[operands.dst].set_u32x4(c);
4676        ControlFlow::Continue(())
4677    }
4678
4679    fn vulteq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4680        let a = self.state[operands.src1].get_u32x4();
4681        let b = self.state[operands.src2].get_u32x4();
4682        let mut c = [0; 4];
4683        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4684            *c = if a <= b { u32::MAX } else { 0 };
4685        }
4686        self.state[operands.dst].set_u32x4(c);
4687        ControlFlow::Continue(())
4688    }
4689
4690    fn veq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4691        let a = self.state[operands.src1].get_u64x2();
4692        let b = self.state[operands.src2].get_u64x2();
4693        let mut c = [0; 2];
4694        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4695            *c = if a == b { u64::MAX } else { 0 };
4696        }
4697        self.state[operands.dst].set_u64x2(c);
4698        ControlFlow::Continue(())
4699    }
4700
4701    fn vneq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4702        let a = self.state[operands.src1].get_u64x2();
4703        let b = self.state[operands.src2].get_u64x2();
4704        let mut c = [0; 2];
4705        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4706            *c = if a != b { u64::MAX } else { 0 };
4707        }
4708        self.state[operands.dst].set_u64x2(c);
4709        ControlFlow::Continue(())
4710    }
4711
4712    fn vslt64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4713        let a = self.state[operands.src1].get_i64x2();
4714        let b = self.state[operands.src2].get_i64x2();
4715        let mut c = [0; 2];
4716        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4717            *c = if a < b { u64::MAX } else { 0 };
4718        }
4719        self.state[operands.dst].set_u64x2(c);
4720        ControlFlow::Continue(())
4721    }
4722
4723    fn vslteq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4724        let a = self.state[operands.src1].get_i64x2();
4725        let b = self.state[operands.src2].get_i64x2();
4726        let mut c = [0; 2];
4727        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4728            *c = if a <= b { u64::MAX } else { 0 };
4729        }
4730        self.state[operands.dst].set_u64x2(c);
4731        ControlFlow::Continue(())
4732    }
4733
4734    fn vult64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4735        let a = self.state[operands.src1].get_u64x2();
4736        let b = self.state[operands.src2].get_u64x2();
4737        let mut c = [0; 2];
4738        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4739            *c = if a < b { u64::MAX } else { 0 };
4740        }
4741        self.state[operands.dst].set_u64x2(c);
4742        ControlFlow::Continue(())
4743    }
4744
4745    fn vulteq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4746        let a = self.state[operands.src1].get_u64x2();
4747        let b = self.state[operands.src2].get_u64x2();
4748        let mut c = [0; 2];
4749        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4750            *c = if a <= b { u64::MAX } else { 0 };
4751        }
4752        self.state[operands.dst].set_u64x2(c);
4753        ControlFlow::Continue(())
4754    }
4755
4756    fn vneg8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4757        let a = self.state[src].get_i8x16();
4758        self.state[dst].set_i8x16(a.map(|i| i.wrapping_neg()));
4759        ControlFlow::Continue(())
4760    }
4761
4762    fn vneg16x8(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4763        let a = self.state[src].get_i16x8();
4764        self.state[dst].set_i16x8(a.map(|i| i.wrapping_neg()));
4765        ControlFlow::Continue(())
4766    }
4767
4768    fn vneg32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4769        let a = self.state[src].get_i32x4();
4770        self.state[dst].set_i32x4(a.map(|i| i.wrapping_neg()));
4771        ControlFlow::Continue(())
4772    }
4773
4774    fn vneg64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4775        let a = self.state[src].get_i64x2();
4776        self.state[dst].set_i64x2(a.map(|i| i.wrapping_neg()));
4777        ControlFlow::Continue(())
4778    }
4779
4780    fn vnegf64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4781        let a = self.state[src].get_f64x2();
4782        self.state[dst].set_f64x2(a.map(|i| -i));
4783        ControlFlow::Continue(())
4784    }
4785
4786    fn vmin8x16_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4787        let mut a = self.state[operands.src1].get_i8x16();
4788        let b = self.state[operands.src2].get_i8x16();
4789        for (a, b) in a.iter_mut().zip(&b) {
4790            *a = (*a).min(*b);
4791        }
4792        self.state[operands.dst].set_i8x16(a);
4793        ControlFlow::Continue(())
4794    }
4795
4796    fn vmin8x16_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4797        let mut a = self.state[operands.src1].get_u8x16();
4798        let b = self.state[operands.src2].get_u8x16();
4799        for (a, b) in a.iter_mut().zip(&b) {
4800            *a = (*a).min(*b);
4801        }
4802        self.state[operands.dst].set_u8x16(a);
4803        ControlFlow::Continue(())
4804    }
4805
4806    fn vmin16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4807        let mut a = self.state[operands.src1].get_i16x8();
4808        let b = self.state[operands.src2].get_i16x8();
4809        for (a, b) in a.iter_mut().zip(&b) {
4810            *a = (*a).min(*b);
4811        }
4812        self.state[operands.dst].set_i16x8(a);
4813        ControlFlow::Continue(())
4814    }
4815
4816    fn vmin16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4817        let mut a = self.state[operands.src1].get_u16x8();
4818        let b = self.state[operands.src2].get_u16x8();
4819        for (a, b) in a.iter_mut().zip(&b) {
4820            *a = (*a).min(*b);
4821        }
4822        self.state[operands.dst].set_u16x8(a);
4823        ControlFlow::Continue(())
4824    }
4825
4826    fn vmin32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4827        let mut a = self.state[operands.src1].get_i32x4();
4828        let b = self.state[operands.src2].get_i32x4();
4829        for (a, b) in a.iter_mut().zip(&b) {
4830            *a = (*a).min(*b);
4831        }
4832        self.state[operands.dst].set_i32x4(a);
4833        ControlFlow::Continue(())
4834    }
4835
4836    fn vmin32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4837        let mut a = self.state[operands.src1].get_u32x4();
4838        let b = self.state[operands.src2].get_u32x4();
4839        for (a, b) in a.iter_mut().zip(&b) {
4840            *a = (*a).min(*b);
4841        }
4842        self.state[operands.dst].set_u32x4(a);
4843        ControlFlow::Continue(())
4844    }
4845
4846    fn vmax8x16_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4847        let mut a = self.state[operands.src1].get_i8x16();
4848        let b = self.state[operands.src2].get_i8x16();
4849        for (a, b) in a.iter_mut().zip(&b) {
4850            *a = (*a).max(*b);
4851        }
4852        self.state[operands.dst].set_i8x16(a);
4853        ControlFlow::Continue(())
4854    }
4855
4856    fn vmax8x16_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4857        let mut a = self.state[operands.src1].get_u8x16();
4858        let b = self.state[operands.src2].get_u8x16();
4859        for (a, b) in a.iter_mut().zip(&b) {
4860            *a = (*a).max(*b);
4861        }
4862        self.state[operands.dst].set_u8x16(a);
4863        ControlFlow::Continue(())
4864    }
4865
4866    fn vmax16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4867        let mut a = self.state[operands.src1].get_i16x8();
4868        let b = self.state[operands.src2].get_i16x8();
4869        for (a, b) in a.iter_mut().zip(&b) {
4870            *a = (*a).max(*b);
4871        }
4872        self.state[operands.dst].set_i16x8(a);
4873        ControlFlow::Continue(())
4874    }
4875
4876    fn vmax16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4877        let mut a = self.state[operands.src1].get_u16x8();
4878        let b = self.state[operands.src2].get_u16x8();
4879        for (a, b) in a.iter_mut().zip(&b) {
4880            *a = (*a).max(*b);
4881        }
4882        self.state[operands.dst].set_u16x8(a);
4883        ControlFlow::Continue(())
4884    }
4885
4886    fn vmax32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4887        let mut a = self.state[operands.src1].get_i32x4();
4888        let b = self.state[operands.src2].get_i32x4();
4889        for (a, b) in a.iter_mut().zip(&b) {
4890            *a = (*a).max(*b);
4891        }
4892        self.state[operands.dst].set_i32x4(a);
4893        ControlFlow::Continue(())
4894    }
4895
4896    fn vmax32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4897        let mut a = self.state[operands.src1].get_u32x4();
4898        let b = self.state[operands.src2].get_u32x4();
4899        for (a, b) in a.iter_mut().zip(&b) {
4900            *a = (*a).max(*b);
4901        }
4902        self.state[operands.dst].set_u32x4(a);
4903        ControlFlow::Continue(())
4904    }
4905
4906    fn vabs8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4907        let a = self.state[src].get_i8x16();
4908        self.state[dst].set_i8x16(a.map(|i| i.wrapping_abs()));
4909        ControlFlow::Continue(())
4910    }
4911
4912    fn vabs16x8(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4913        let a = self.state[src].get_i16x8();
4914        self.state[dst].set_i16x8(a.map(|i| i.wrapping_abs()));
4915        ControlFlow::Continue(())
4916    }
4917
4918    fn vabs32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4919        let a = self.state[src].get_i32x4();
4920        self.state[dst].set_i32x4(a.map(|i| i.wrapping_abs()));
4921        ControlFlow::Continue(())
4922    }
4923
4924    fn vabs64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4925        let a = self.state[src].get_i64x2();
4926        self.state[dst].set_i64x2(a.map(|i| i.wrapping_abs()));
4927        ControlFlow::Continue(())
4928    }
4929
4930    fn vabsf32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4931        let a = self.state[src].get_f32x4();
4932        self.state[dst].set_f32x4(a.map(|i| i.wasm_abs()));
4933        ControlFlow::Continue(())
4934    }
4935
4936    fn vabsf64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4937        let a = self.state[src].get_f64x2();
4938        self.state[dst].set_f64x2(a.map(|i| i.wasm_abs()));
4939        ControlFlow::Continue(())
4940    }
4941
4942    fn vmaximumf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4943        let mut a = self.state[operands.src1].get_f32x4();
4944        let b = self.state[operands.src2].get_f32x4();
4945        for (a, b) in a.iter_mut().zip(&b) {
4946            *a = a.wasm_maximum(*b);
4947        }
4948        self.state[operands.dst].set_f32x4(a);
4949        ControlFlow::Continue(())
4950    }
4951
4952    fn vmaximumf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4953        let mut a = self.state[operands.src1].get_f64x2();
4954        let b = self.state[operands.src2].get_f64x2();
4955        for (a, b) in a.iter_mut().zip(&b) {
4956            *a = a.wasm_maximum(*b);
4957        }
4958        self.state[operands.dst].set_f64x2(a);
4959        ControlFlow::Continue(())
4960    }
4961
4962    fn vminimumf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4963        let mut a = self.state[operands.src1].get_f32x4();
4964        let b = self.state[operands.src2].get_f32x4();
4965        for (a, b) in a.iter_mut().zip(&b) {
4966            *a = a.wasm_minimum(*b);
4967        }
4968        self.state[operands.dst].set_f32x4(a);
4969        ControlFlow::Continue(())
4970    }
4971
4972    fn vminimumf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4973        let mut a = self.state[operands.src1].get_f64x2();
4974        let b = self.state[operands.src2].get_f64x2();
4975        for (a, b) in a.iter_mut().zip(&b) {
4976            *a = a.wasm_minimum(*b);
4977        }
4978        self.state[operands.dst].set_f64x2(a);
4979        ControlFlow::Continue(())
4980    }
4981
4982    fn vshuffle(&mut self, dst: VReg, src1: VReg, src2: VReg, mask: u128) -> ControlFlow<Done> {
4983        let a = self.state[src1].get_u8x16();
4984        let b = self.state[src2].get_u8x16();
4985        let result = mask.to_le_bytes().map(|m| {
4986            if m < 16 {
4987                a[m as usize]
4988            } else {
4989                b[m as usize - 16]
4990            }
4991        });
4992        self.state[dst].set_u8x16(result);
4993        ControlFlow::Continue(())
4994    }
4995
4996    fn vswizzlei8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4997        let src1 = self.state[operands.src1].get_i8x16();
4998        let src2 = self.state[operands.src2].get_i8x16();
4999        let mut dst = [0i8; 16];
5000        for (i, &idx) in src2.iter().enumerate() {
5001            if (idx as usize) < 16 {
5002                dst[i] = src1[idx as usize];
5003            } else {
5004                dst[i] = 0
5005            }
5006        }
5007        self.state[operands.dst].set_i8x16(dst);
5008        ControlFlow::Continue(())
5009    }
5010
5011    fn vavground8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5012        let mut a = self.state[operands.src1].get_u8x16();
5013        let b = self.state[operands.src2].get_u8x16();
5014        for (a, b) in a.iter_mut().zip(&b) {
5015            // use wider precision to avoid overflow
5016            *a = ((u32::from(*a) + u32::from(*b) + 1) / 2) as u8;
5017        }
5018        self.state[operands.dst].set_u8x16(a);
5019        ControlFlow::Continue(())
5020    }
5021
5022    fn vavground16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5023        let mut a = self.state[operands.src1].get_u16x8();
5024        let b = self.state[operands.src2].get_u16x8();
5025        for (a, b) in a.iter_mut().zip(&b) {
5026            // use wider precision to avoid overflow
5027            *a = ((u32::from(*a) + u32::from(*b) + 1) / 2) as u16;
5028        }
5029        self.state[operands.dst].set_u16x8(a);
5030        ControlFlow::Continue(())
5031    }
5032
5033    fn veqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5034        let a = self.state[operands.src1].get_f32x4();
5035        let b = self.state[operands.src2].get_f32x4();
5036        let mut c = [0; 4];
5037        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5038            *c = if a == b { u32::MAX } else { 0 };
5039        }
5040        self.state[operands.dst].set_u32x4(c);
5041        ControlFlow::Continue(())
5042    }
5043
5044    fn vneqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5045        let a = self.state[operands.src1].get_f32x4();
5046        let b = self.state[operands.src2].get_f32x4();
5047        let mut c = [0; 4];
5048        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5049            *c = if a != b { u32::MAX } else { 0 };
5050        }
5051        self.state[operands.dst].set_u32x4(c);
5052        ControlFlow::Continue(())
5053    }
5054
5055    fn vltf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5056        let a = self.state[operands.src1].get_f32x4();
5057        let b = self.state[operands.src2].get_f32x4();
5058        let mut c = [0; 4];
5059        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5060            *c = if a < b { u32::MAX } else { 0 };
5061        }
5062        self.state[operands.dst].set_u32x4(c);
5063        ControlFlow::Continue(())
5064    }
5065
5066    fn vlteqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5067        let a = self.state[operands.src1].get_f32x4();
5068        let b = self.state[operands.src2].get_f32x4();
5069        let mut c = [0; 4];
5070        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5071            *c = if a <= b { u32::MAX } else { 0 };
5072        }
5073        self.state[operands.dst].set_u32x4(c);
5074        ControlFlow::Continue(())
5075    }
5076
5077    fn veqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5078        let a = self.state[operands.src1].get_f64x2();
5079        let b = self.state[operands.src2].get_f64x2();
5080        let mut c = [0; 2];
5081        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5082            *c = if a == b { u64::MAX } else { 0 };
5083        }
5084        self.state[operands.dst].set_u64x2(c);
5085        ControlFlow::Continue(())
5086    }
5087
5088    fn vneqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5089        let a = self.state[operands.src1].get_f64x2();
5090        let b = self.state[operands.src2].get_f64x2();
5091        let mut c = [0; 2];
5092        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5093            *c = if a != b { u64::MAX } else { 0 };
5094        }
5095        self.state[operands.dst].set_u64x2(c);
5096        ControlFlow::Continue(())
5097    }
5098
5099    fn vltf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5100        let a = self.state[operands.src1].get_f64x2();
5101        let b = self.state[operands.src2].get_f64x2();
5102        let mut c = [0; 2];
5103        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5104            *c = if a < b { u64::MAX } else { 0 };
5105        }
5106        self.state[operands.dst].set_u64x2(c);
5107        ControlFlow::Continue(())
5108    }
5109
5110    fn vlteqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5111        let a = self.state[operands.src1].get_f64x2();
5112        let b = self.state[operands.src2].get_f64x2();
5113        let mut c = [0; 2];
5114        for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5115            *c = if a <= b { u64::MAX } else { 0 };
5116        }
5117        self.state[operands.dst].set_u64x2(c);
5118        ControlFlow::Continue(())
5119    }
5120
5121    fn vfma32x4(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
5122        let mut a = self.state[a].get_f32x4();
5123        let b = self.state[b].get_f32x4();
5124        let c = self.state[c].get_f32x4();
5125        for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
5126            *a = a.wasm_mul_add(b, c);
5127        }
5128        self.state[dst].set_f32x4(a);
5129        ControlFlow::Continue(())
5130    }
5131
5132    fn vfma64x2(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
5133        let mut a = self.state[a].get_f64x2();
5134        let b = self.state[b].get_f64x2();
5135        let c = self.state[c].get_f64x2();
5136        for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
5137            *a = a.wasm_mul_add(b, c);
5138        }
5139        self.state[dst].set_f64x2(a);
5140        ControlFlow::Continue(())
5141    }
5142
5143    fn vselect(
5144        &mut self,
5145        dst: VReg,
5146        cond: XReg,
5147        if_nonzero: VReg,
5148        if_zero: VReg,
5149    ) -> ControlFlow<Done> {
5150        let result = if self.state[cond].get_u32() != 0 {
5151            self.state[if_nonzero]
5152        } else {
5153            self.state[if_zero]
5154        };
5155        self.state[dst] = result;
5156        ControlFlow::Continue(())
5157    }
5158
5159    fn xadd128(
5160        &mut self,
5161        dst_lo: XReg,
5162        dst_hi: XReg,
5163        lhs_lo: XReg,
5164        lhs_hi: XReg,
5165        rhs_lo: XReg,
5166        rhs_hi: XReg,
5167    ) -> ControlFlow<Done> {
5168        let lhs = self.get_i128(lhs_lo, lhs_hi);
5169        let rhs = self.get_i128(rhs_lo, rhs_hi);
5170        let result = lhs.wrapping_add(rhs);
5171        self.set_i128(dst_lo, dst_hi, result);
5172        ControlFlow::Continue(())
5173    }
5174
5175    fn xsub128(
5176        &mut self,
5177        dst_lo: XReg,
5178        dst_hi: XReg,
5179        lhs_lo: XReg,
5180        lhs_hi: XReg,
5181        rhs_lo: XReg,
5182        rhs_hi: XReg,
5183    ) -> ControlFlow<Done> {
5184        let lhs = self.get_i128(lhs_lo, lhs_hi);
5185        let rhs = self.get_i128(rhs_lo, rhs_hi);
5186        let result = lhs.wrapping_sub(rhs);
5187        self.set_i128(dst_lo, dst_hi, result);
5188        ControlFlow::Continue(())
5189    }
5190
5191    fn xwidemul64_s(
5192        &mut self,
5193        dst_lo: XReg,
5194        dst_hi: XReg,
5195        lhs: XReg,
5196        rhs: XReg,
5197    ) -> ControlFlow<Done> {
5198        let lhs = self.state[lhs].get_i64();
5199        let rhs = self.state[rhs].get_i64();
5200        let result = i128::from(lhs).wrapping_mul(i128::from(rhs));
5201        self.set_i128(dst_lo, dst_hi, result);
5202        ControlFlow::Continue(())
5203    }
5204
5205    fn xwidemul64_u(
5206        &mut self,
5207        dst_lo: XReg,
5208        dst_hi: XReg,
5209        lhs: XReg,
5210        rhs: XReg,
5211    ) -> ControlFlow<Done> {
5212        let lhs = self.state[lhs].get_u64();
5213        let rhs = self.state[rhs].get_u64();
5214        let result = u128::from(lhs).wrapping_mul(u128::from(rhs));
5215        self.set_i128(dst_lo, dst_hi, result as i128);
5216        ControlFlow::Continue(())
5217    }
5218}