1use crate::decode::*;
4use crate::encode::Encode;
5use crate::imms::*;
6use crate::profile::{ExecutingPc, ExecutingPcRef};
7use crate::regs::*;
8use alloc::string::ToString;
9use core::fmt;
10use core::mem;
11use core::ops::ControlFlow;
12use core::ops::{Index, IndexMut};
13use core::ptr::NonNull;
14use pulley_macros::interp_disable_if_cfg;
15use wasmtime_core::alloc::TryVec;
16use wasmtime_core::error::OutOfMemory;
17use wasmtime_core::math::{WasmFloat, f32_cvt_to_int_bounds, f64_cvt_to_int_bounds};
18
19mod debug;
20#[cfg(all(not(pulley_tail_calls), not(pulley_assume_llvm_makes_tail_calls)))]
21mod match_loop;
22#[cfg(any(pulley_tail_calls, pulley_assume_llvm_makes_tail_calls))]
23mod tail_loop;
24
25const DEFAULT_STACK_SIZE: usize = 1 << 20; pub struct Vm {
29 state: MachineState,
30 executing_pc: ExecutingPc,
31}
32
33impl Vm {
34 pub fn new() -> Result<Self, OutOfMemory> {
36 Self::with_stack(DEFAULT_STACK_SIZE)
37 }
38
39 pub fn with_stack(stack_size: usize) -> Result<Self, OutOfMemory> {
41 Ok(Self {
42 state: MachineState::with_stack(stack_size)?,
43 executing_pc: ExecutingPc::default(),
44 })
45 }
46
47 pub fn state(&self) -> &MachineState {
49 &self.state
50 }
51
52 pub fn state_mut(&mut self) -> &mut MachineState {
54 &mut self.state
55 }
56
57 pub unsafe fn call<'a, T>(
70 &'a mut self,
71 func: NonNull<u8>,
72 args: &[Val],
73 rets: T,
74 ) -> DoneReason<impl Iterator<Item = Val> + use<'a, T>>
75 where
76 T: IntoIterator<Item = RegType> + 'a,
77 {
78 unsafe {
79 let lr = self.call_start(args);
80
81 match self.call_run(func) {
82 DoneReason::ReturnToHost(()) => DoneReason::ReturnToHost(self.call_end(lr, rets)),
83 DoneReason::Trap { pc, kind } => DoneReason::Trap { pc, kind },
84 DoneReason::CallIndirectHost { id, resume } => {
85 DoneReason::CallIndirectHost { id, resume }
86 }
87 }
88 }
89 }
90
91 pub unsafe fn call_start<'a>(&'a mut self, args: &[Val]) -> *mut u8 {
106 let mut x_args = (0..15).map(|x| unsafe { XReg::new_unchecked(x) });
110 let mut f_args = (0..16).map(|f| unsafe { FReg::new_unchecked(f) });
111 #[cfg(not(pulley_disable_interp_simd))]
112 let mut v_args = (0..16).map(|v| unsafe { 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 #[cfg(not(pulley_disable_interp_simd))]
125 Val::VReg(val) => match v_args.next() {
126 Some(reg) => self.state[reg] = *val,
127 None => todo!("stack slots"),
128 },
129 }
130 }
131
132 mem::replace(&mut self.state.lr, HOST_RETURN_ADDR)
133 }
134
135 pub unsafe fn call_run(&mut self, pc: NonNull<u8>) -> DoneReason<()> {
144 self.state.debug_assert_done_reason_none();
145 let interpreter = Interpreter {
146 state: &mut self.state,
147 pc: unsafe { UnsafeBytecodeStream::new(pc) },
148 executing_pc: self.executing_pc.as_ref(),
149 };
150 let done = interpreter.run();
151 self.state.done_decode(done)
152 }
153
154 pub unsafe fn call_end<'a>(
165 &'a mut self,
166 old_ret: *mut u8,
167 rets: impl IntoIterator<Item = RegType> + 'a,
168 ) -> impl Iterator<Item = Val> + 'a {
169 self.state.lr = old_ret;
170 let mut x_rets = (0..15).map(|x| unsafe { XReg::new_unchecked(x) });
174 let mut f_rets = (0..16).map(|f| unsafe { FReg::new_unchecked(f) });
175 #[cfg(not(pulley_disable_interp_simd))]
176 let mut v_rets = (0..16).map(|v| unsafe { VReg::new_unchecked(v) });
177
178 rets.into_iter().map(move |ty| match ty {
179 RegType::XReg => match x_rets.next() {
180 Some(reg) => Val::XReg(self.state[reg]),
181 None => todo!("stack slots"),
182 },
183 RegType::FReg => match f_rets.next() {
184 Some(reg) => Val::FReg(self.state[reg]),
185 None => todo!("stack slots"),
186 },
187 #[cfg(not(pulley_disable_interp_simd))]
188 RegType::VReg => match v_rets.next() {
189 Some(reg) => Val::VReg(self.state[reg]),
190 None => todo!("stack slots"),
191 },
192 #[cfg(pulley_disable_interp_simd)]
193 RegType::VReg => panic!("simd support disabled at compile time"),
194 })
195 }
196
197 pub fn fp(&self) -> *mut u8 {
199 self.state.fp
200 }
201
202 pub fn lr(&self) -> *mut u8 {
204 self.state.lr
205 }
206
207 pub fn lr_is_host_return(&self) -> bool {
210 self.state.lr == HOST_RETURN_ADDR
211 }
212
213 pub unsafe fn set_fp(&mut self, fp: *mut u8) {
215 self.state.fp = fp;
216 }
217
218 pub unsafe fn set_lr(&mut self, lr: *mut u8) {
220 self.state.lr = lr;
221 }
222
223 #[cfg(feature = "profile")]
230 pub fn executing_pc(&self) -> &ExecutingPc {
231 &self.executing_pc
232 }
233}
234
235impl Drop for Vm {
236 fn drop(&mut self) {
237 self.executing_pc.set_done();
238 }
239}
240
241#[derive(Clone, Copy, Debug)]
243pub enum RegType {
244 XReg,
246
247 FReg,
249
250 VReg,
252}
253
254#[derive(Clone, Copy, Debug)]
256pub enum Val {
257 XReg(XRegVal),
259
260 FReg(FRegVal),
262
263 #[cfg(not(pulley_disable_interp_simd))]
265 VReg(VRegVal),
266}
267
268impl fmt::LowerHex for Val {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 match self {
271 Val::XReg(v) => fmt::LowerHex::fmt(v, f),
272 Val::FReg(v) => fmt::LowerHex::fmt(v, f),
273 #[cfg(not(pulley_disable_interp_simd))]
274 Val::VReg(v) => fmt::LowerHex::fmt(v, f),
275 }
276 }
277}
278
279impl From<XRegVal> for Val {
280 fn from(value: XRegVal) -> Self {
281 Val::XReg(value)
282 }
283}
284
285impl From<u64> for Val {
286 fn from(value: u64) -> Self {
287 XRegVal::new_u64(value).into()
288 }
289}
290
291impl From<u32> for Val {
292 fn from(value: u32) -> Self {
293 XRegVal::new_u32(value).into()
294 }
295}
296
297impl From<i64> for Val {
298 fn from(value: i64) -> Self {
299 XRegVal::new_i64(value).into()
300 }
301}
302
303impl From<i32> for Val {
304 fn from(value: i32) -> Self {
305 XRegVal::new_i32(value).into()
306 }
307}
308
309impl<T> From<*mut T> for Val {
310 fn from(value: *mut T) -> Self {
311 XRegVal::new_ptr(value).into()
312 }
313}
314
315impl From<FRegVal> for Val {
316 fn from(value: FRegVal) -> Self {
317 Val::FReg(value)
318 }
319}
320
321impl From<f64> for Val {
322 fn from(value: f64) -> Self {
323 FRegVal::new_f64(value).into()
324 }
325}
326
327impl From<f32> for Val {
328 fn from(value: f32) -> Self {
329 FRegVal::new_f32(value).into()
330 }
331}
332
333#[cfg(not(pulley_disable_interp_simd))]
334impl From<VRegVal> for Val {
335 fn from(value: VRegVal) -> Self {
336 Val::VReg(value)
337 }
338}
339
340#[derive(Copy, Clone)]
342pub struct XRegVal(XRegUnion);
343
344impl PartialEq for XRegVal {
345 fn eq(&self, other: &Self) -> bool {
346 self.get_u64() == other.get_u64()
347 }
348}
349
350impl Eq for XRegVal {}
351
352impl fmt::Debug for XRegVal {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 f.debug_struct("XRegVal")
355 .field("as_u64", &self.get_u64())
356 .finish()
357 }
358}
359
360impl fmt::LowerHex for XRegVal {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 fmt::LowerHex::fmt(&self.get_u64(), f)
363 }
364}
365
366#[derive(Copy, Clone)]
410union XRegUnion {
411 i32: i32,
412 u32: u32,
413 i64: i64,
414 u64: u64,
415
416 ptr: usize,
427}
428
429impl Default for XRegVal {
430 fn default() -> Self {
431 Self(unsafe { mem::zeroed() })
432 }
433}
434
435#[expect(missing_docs, reason = "self-describing methods")]
436impl XRegVal {
437 pub fn new_i32(x: i32) -> Self {
438 let mut val = XRegVal::default();
439 val.set_i32(x);
440 val
441 }
442
443 pub fn new_u32(x: u32) -> Self {
444 let mut val = XRegVal::default();
445 val.set_u32(x);
446 val
447 }
448
449 pub fn new_i64(x: i64) -> Self {
450 let mut val = XRegVal::default();
451 val.set_i64(x);
452 val
453 }
454
455 pub fn new_u64(x: u64) -> Self {
456 let mut val = XRegVal::default();
457 val.set_u64(x);
458 val
459 }
460
461 pub fn new_ptr<T>(ptr: *mut T) -> Self {
462 let mut val = XRegVal::default();
463 val.set_ptr(ptr);
464 val
465 }
466
467 pub fn get_i32(&self) -> i32 {
468 let x = unsafe { self.0.i32 };
469 i32::from_le(x)
470 }
471
472 pub fn get_u32(&self) -> u32 {
473 let x = unsafe { self.0.u32 };
474 u32::from_le(x)
475 }
476
477 pub fn get_i64(&self) -> i64 {
478 let x = unsafe { self.0.i64 };
479 i64::from_le(x)
480 }
481
482 pub fn get_u64(&self) -> u64 {
483 let x = unsafe { self.0.u64 };
484 u64::from_le(x)
485 }
486
487 pub fn get_ptr<T>(&self) -> *mut T {
488 let ptr = unsafe { self.0.ptr };
489 core::ptr::with_exposed_provenance_mut(usize::from_le(ptr))
490 }
491
492 pub fn set_i32(&mut self, x: i32) {
493 self.0.i32 = x.to_le();
494 }
495
496 pub fn set_u32(&mut self, x: u32) {
497 self.0.u32 = x.to_le();
498 }
499
500 pub fn set_i64(&mut self, x: i64) {
501 self.0.i64 = x.to_le();
502 }
503
504 pub fn set_u64(&mut self, x: u64) {
505 self.0.u64 = x.to_le();
506 }
507
508 pub fn set_ptr<T>(&mut self, ptr: *mut T) {
509 self.0.ptr = ptr.expose_provenance().to_le();
510 }
511}
512
513#[derive(Copy, Clone)]
515pub struct FRegVal(FRegUnion);
516
517impl fmt::Debug for FRegVal {
518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519 f.debug_struct("FRegVal")
520 .field("as_f32", &self.get_f32())
521 .field("as_f64", &self.get_f64())
522 .finish()
523 }
524}
525
526impl fmt::LowerHex for FRegVal {
527 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528 fmt::LowerHex::fmt(&self.get_f64().to_bits(), f)
529 }
530}
531
532#[derive(Copy, Clone)]
535union FRegUnion {
536 f32: u32,
537 f64: u64,
538}
539
540impl Default for FRegVal {
541 fn default() -> Self {
542 Self(unsafe { mem::zeroed() })
543 }
544}
545
546#[expect(missing_docs, reason = "self-describing methods")]
547impl FRegVal {
548 pub fn new_f32(f: f32) -> Self {
549 let mut val = Self::default();
550 val.set_f32(f);
551 val
552 }
553
554 pub fn new_f64(f: f64) -> Self {
555 let mut val = Self::default();
556 val.set_f64(f);
557 val
558 }
559
560 pub fn get_f32(&self) -> f32 {
561 let val = unsafe { self.0.f32 };
562 f32::from_le_bytes(val.to_ne_bytes())
563 }
564
565 pub fn get_f64(&self) -> f64 {
566 let val = unsafe { self.0.f64 };
567 f64::from_le_bytes(val.to_ne_bytes())
568 }
569
570 pub fn set_f32(&mut self, val: f32) {
571 self.0.f32 = u32::from_ne_bytes(val.to_le_bytes());
572 }
573
574 pub fn set_f64(&mut self, val: f64) {
575 self.0.f64 = u64::from_ne_bytes(val.to_le_bytes());
576 }
577}
578
579#[derive(Copy, Clone)]
581#[cfg(not(pulley_disable_interp_simd))]
582pub struct VRegVal(VRegUnion);
583
584#[cfg(not(pulley_disable_interp_simd))]
585impl fmt::Debug for VRegVal {
586 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587 f.debug_struct("VRegVal")
588 .field("as_u128", &unsafe { self.0.u128 })
589 .finish()
590 }
591}
592
593#[cfg(not(pulley_disable_interp_simd))]
594impl fmt::LowerHex for VRegVal {
595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
596 fmt::LowerHex::fmt(unsafe { &self.0.u128 }, f)
597 }
598}
599
600#[derive(Copy, Clone)]
608#[repr(align(16))]
609#[cfg(not(pulley_disable_interp_simd))]
610union VRegUnion {
611 u128: u128,
612 i8x16: [i8; 16],
613 i16x8: [i16; 8],
614 i32x4: [i32; 4],
615 i64x2: [i64; 2],
616 u8x16: [u8; 16],
617 u16x8: [u16; 8],
618 u32x4: [u32; 4],
619 u64x2: [u64; 2],
620 f32x4: [u32; 4],
624 f64x2: [u64; 2],
625}
626
627#[cfg(not(pulley_disable_interp_simd))]
628impl Default for VRegVal {
629 fn default() -> Self {
630 Self(unsafe { mem::zeroed() })
631 }
632}
633
634#[expect(missing_docs, reason = "self-describing methods")]
635#[cfg(not(pulley_disable_interp_simd))]
636impl VRegVal {
637 pub fn new_u128(i: u128) -> Self {
638 let mut val = Self::default();
639 val.set_u128(i);
640 val
641 }
642
643 pub fn get_u128(&self) -> u128 {
644 let val = unsafe { self.0.u128 };
645 u128::from_le(val)
646 }
647
648 pub fn set_u128(&mut self, val: u128) {
649 self.0.u128 = val.to_le();
650 }
651
652 fn get_i8x16(&self) -> [i8; 16] {
653 let val = unsafe { self.0.i8x16 };
654 val.map(|e| i8::from_le(e))
655 }
656
657 fn set_i8x16(&mut self, val: [i8; 16]) {
658 self.0.i8x16 = val.map(|e| e.to_le());
659 }
660
661 fn get_u8x16(&self) -> [u8; 16] {
662 let val = unsafe { self.0.u8x16 };
663 val.map(|e| u8::from_le(e))
664 }
665
666 fn set_u8x16(&mut self, val: [u8; 16]) {
667 self.0.u8x16 = val.map(|e| e.to_le());
668 }
669
670 fn get_i16x8(&self) -> [i16; 8] {
671 let val = unsafe { self.0.i16x8 };
672 val.map(|e| i16::from_le(e))
673 }
674
675 fn set_i16x8(&mut self, val: [i16; 8]) {
676 self.0.i16x8 = val.map(|e| e.to_le());
677 }
678
679 fn get_u16x8(&self) -> [u16; 8] {
680 let val = unsafe { self.0.u16x8 };
681 val.map(|e| u16::from_le(e))
682 }
683
684 fn set_u16x8(&mut self, val: [u16; 8]) {
685 self.0.u16x8 = val.map(|e| e.to_le());
686 }
687
688 fn get_i32x4(&self) -> [i32; 4] {
689 let val = unsafe { self.0.i32x4 };
690 val.map(|e| i32::from_le(e))
691 }
692
693 fn set_i32x4(&mut self, val: [i32; 4]) {
694 self.0.i32x4 = val.map(|e| e.to_le());
695 }
696
697 fn get_u32x4(&self) -> [u32; 4] {
698 let val = unsafe { self.0.u32x4 };
699 val.map(|e| u32::from_le(e))
700 }
701
702 fn set_u32x4(&mut self, val: [u32; 4]) {
703 self.0.u32x4 = val.map(|e| e.to_le());
704 }
705
706 fn get_i64x2(&self) -> [i64; 2] {
707 let val = unsafe { self.0.i64x2 };
708 val.map(|e| i64::from_le(e))
709 }
710
711 fn set_i64x2(&mut self, val: [i64; 2]) {
712 self.0.i64x2 = val.map(|e| e.to_le());
713 }
714
715 fn get_u64x2(&self) -> [u64; 2] {
716 let val = unsafe { self.0.u64x2 };
717 val.map(|e| u64::from_le(e))
718 }
719
720 fn set_u64x2(&mut self, val: [u64; 2]) {
721 self.0.u64x2 = val.map(|e| e.to_le());
722 }
723
724 fn get_f64x2(&self) -> [f64; 2] {
725 let val = unsafe { self.0.f64x2 };
726 val.map(|e| f64::from_bits(u64::from_le(e)))
727 }
728
729 fn set_f64x2(&mut self, val: [f64; 2]) {
730 self.0.f64x2 = val.map(|e| e.to_bits().to_le());
731 }
732
733 fn get_f32x4(&self) -> [f32; 4] {
734 let val = unsafe { self.0.f32x4 };
735 val.map(|e| f32::from_bits(u32::from_le(e)))
736 }
737
738 fn set_f32x4(&mut self, val: [f32; 4]) {
739 self.0.f32x4 = val.map(|e| e.to_bits().to_le());
740 }
741}
742
743pub struct MachineState {
746 x_regs: [XRegVal; XReg::RANGE.end as usize],
747 f_regs: [FRegVal; FReg::RANGE.end as usize],
748 #[cfg(not(pulley_disable_interp_simd))]
749 v_regs: [VRegVal; VReg::RANGE.end as usize],
750 fp: *mut u8,
751 lr: *mut u8,
752 stack: Stack,
753 done_reason: Option<DoneReason<()>>,
754}
755
756unsafe impl Send for MachineState {}
757unsafe impl Sync for MachineState {}
758
759struct Stack {
766 storage: TryVec<Align16>,
767}
768
769#[derive(Copy, Clone)]
771#[repr(align(16))]
772struct Align16 {
773 _unused: u128,
776}
777
778impl Stack {
779 fn new(size: usize) -> Result<Stack, OutOfMemory> {
783 let mut storage = TryVec::new();
784 storage.reserve_exact(size.checked_next_multiple_of(16).unwrap_or(usize::MAX) / 16)?;
789 Ok(Stack { storage })
790 }
791
792 fn top(&mut self) -> *mut u8 {
797 let len = self.len();
798 unsafe { self.base().add(len) }
799 }
800
801 fn base(&mut self) -> *mut u8 {
806 self.storage.as_mut_ptr().cast::<u8>()
807 }
808
809 fn len(&self) -> usize {
811 self.storage.capacity() * mem::size_of::<Align16>()
812 }
813}
814
815impl fmt::Debug for MachineState {
816 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817 let MachineState {
818 x_regs,
819 f_regs,
820 #[cfg(not(pulley_disable_interp_simd))]
821 v_regs,
822 stack: _,
823 done_reason: _,
824 fp: _,
825 lr: _,
826 } = self;
827
828 struct RegMap<'a, R>(&'a [R], fn(u8) -> alloc::string::String);
829
830 impl<R: fmt::Debug> fmt::Debug for RegMap<'_, R> {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 let mut f = f.debug_map();
833 for (i, r) in self.0.iter().enumerate() {
834 f.entry(&(self.1)(i as u8), r);
835 }
836 f.finish()
837 }
838 }
839
840 let mut f = f.debug_struct("MachineState");
841
842 f.field(
843 "x_regs",
844 &RegMap(x_regs, |i| XReg::new(i).unwrap().to_string()),
845 )
846 .field(
847 "f_regs",
848 &RegMap(f_regs, |i| FReg::new(i).unwrap().to_string()),
849 );
850 #[cfg(not(pulley_disable_interp_simd))]
851 f.field(
852 "v_regs",
853 &RegMap(v_regs, |i| VReg::new(i).unwrap().to_string()),
854 );
855 f.finish_non_exhaustive()
856 }
857}
858
859macro_rules! index_reg {
860 ($reg_ty:ty,$value_ty:ty,$field:ident) => {
861 impl Index<$reg_ty> for Vm {
862 type Output = $value_ty;
863
864 fn index(&self, reg: $reg_ty) -> &Self::Output {
865 &self.state[reg]
866 }
867 }
868
869 impl IndexMut<$reg_ty> for Vm {
870 fn index_mut(&mut self, reg: $reg_ty) -> &mut Self::Output {
871 &mut self.state[reg]
872 }
873 }
874
875 impl Index<$reg_ty> for MachineState {
876 type Output = $value_ty;
877
878 fn index(&self, reg: $reg_ty) -> &Self::Output {
879 &self.$field[reg.index()]
880 }
881 }
882
883 impl IndexMut<$reg_ty> for MachineState {
884 fn index_mut(&mut self, reg: $reg_ty) -> &mut Self::Output {
885 &mut self.$field[reg.index()]
886 }
887 }
888 };
889}
890
891index_reg!(XReg, XRegVal, x_regs);
892index_reg!(FReg, FRegVal, f_regs);
893#[cfg(not(pulley_disable_interp_simd))]
894index_reg!(VReg, VRegVal, v_regs);
895
896const HOST_RETURN_ADDR: *mut u8 = usize::MAX as *mut u8;
898
899impl MachineState {
900 fn with_stack(stack_size: usize) -> Result<Self, OutOfMemory> {
901 let mut state = Self {
902 x_regs: [Default::default(); XReg::RANGE.end as usize],
903 f_regs: Default::default(),
904 #[cfg(not(pulley_disable_interp_simd))]
905 v_regs: Default::default(),
906 stack: Stack::new(stack_size)?,
907 done_reason: None,
908 fp: HOST_RETURN_ADDR,
909 lr: HOST_RETURN_ADDR,
910 };
911
912 let sp = state.stack.top();
913 state[XReg::sp] = XRegVal::new_ptr(sp);
914
915 Ok(state)
916 }
917}
918
919mod done {
922 use super::{Encode, Interpreter, MachineState};
923 use core::ops::ControlFlow;
924 use core::ptr::NonNull;
925
926 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
930 pub struct Done {
931 _priv: (),
932 }
933
934 pub enum DoneReason<T> {
936 Trap {
938 pc: NonNull<u8>,
940 kind: Option<TrapKind>,
942 },
943 CallIndirectHost {
945 id: u8,
947 resume: NonNull<u8>,
949 },
950 ReturnToHost(T),
952 }
953
954 #[expect(missing_docs, reason = "self-describing variants")]
956 pub enum TrapKind {
957 DivideByZero,
958 IntegerOverflow,
959 BadConversionToInteger,
960 MemoryOutOfBounds,
961 DisabledOpcode,
962 StackOverflow,
963 }
964
965 impl MachineState {
966 pub(super) fn debug_assert_done_reason_none(&mut self) {
967 debug_assert!(self.done_reason.is_none());
968 }
969
970 pub(super) fn done_decode(&mut self, Done { _priv }: Done) -> DoneReason<()> {
971 self.done_reason.take().unwrap()
972 }
973 }
974
975 impl Interpreter<'_> {
976 #[cold]
984 pub fn done_trap<I: Encode>(&mut self) -> ControlFlow<Done> {
985 self.done_trap_kind::<I>(None)
986 }
987
988 #[cold]
990 pub fn done_trap_kind<I: Encode>(&mut self, kind: Option<TrapKind>) -> ControlFlow<Done> {
991 let pc = self.current_pc::<I>();
992 self.state.done_reason = Some(DoneReason::Trap { pc, kind });
993 ControlFlow::Break(Done { _priv: () })
994 }
995
996 #[cold]
998 pub fn done_call_indirect_host(&mut self, id: u8) -> ControlFlow<Done> {
999 self.state.done_reason = Some(DoneReason::CallIndirectHost {
1000 id,
1001 resume: self.pc.as_ptr(),
1002 });
1003 ControlFlow::Break(Done { _priv: () })
1004 }
1005
1006 #[cold]
1008 pub fn done_return_to_host(&mut self) -> ControlFlow<Done> {
1009 self.state.done_reason = Some(DoneReason::ReturnToHost(()));
1010 ControlFlow::Break(Done { _priv: () })
1011 }
1012 }
1013}
1014
1015use done::Done;
1016pub use done::{DoneReason, TrapKind};
1017
1018struct Interpreter<'a> {
1019 state: &'a mut MachineState,
1020 pc: UnsafeBytecodeStream,
1021 executing_pc: ExecutingPcRef<'a>,
1022}
1023
1024impl Interpreter<'_> {
1025 #[inline]
1027 fn pc_rel<I: Encode>(&mut self, offset: PcRelOffset) -> NonNull<u8> {
1028 let offset = isize::try_from(i32::from(offset)).unwrap();
1029 unsafe { self.current_pc::<I>().offset(offset) }
1030 }
1031
1032 #[inline]
1039 fn pc_rel_jump<I: Encode>(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1040 let new_pc = self.pc_rel::<I>(offset);
1041 self.pc = unsafe { UnsafeBytecodeStream::new(new_pc) };
1042 ControlFlow::Continue(())
1043 }
1044
1045 fn current_pc<I: Encode>(&self) -> NonNull<u8> {
1048 unsafe { self.pc.offset(-isize::from(I::WIDTH)).as_ptr() }
1049 }
1050
1051 #[must_use]
1056 fn push<I: Encode, T>(&mut self, val: T) -> ControlFlow<Done> {
1057 let new_sp = self.state[XReg::sp].get_ptr::<T>().wrapping_sub(1);
1058 self.set_sp::<I>(new_sp.cast())?;
1059 unsafe {
1060 new_sp.write_unaligned(val);
1061 }
1062 ControlFlow::Continue(())
1063 }
1064
1065 fn pop<T>(&mut self) -> T {
1067 let sp = self.state[XReg::sp].get_ptr::<T>();
1068 let val = unsafe { sp.read_unaligned() };
1069 self.set_sp_unchecked(sp.wrapping_add(1));
1070 val
1071 }
1072
1073 #[must_use]
1082 fn set_sp<I: Encode>(&mut self, sp: *mut u8) -> ControlFlow<Done> {
1083 let sp_raw = sp as usize;
1084 let base_raw = self.state.stack.base() as usize;
1085 if sp_raw < base_raw {
1086 return self.done_trap_kind::<I>(Some(TrapKind::StackOverflow));
1087 }
1088 self.set_sp_unchecked(sp);
1089 ControlFlow::Continue(())
1090 }
1091
1092 fn set_sp_unchecked<T>(&mut self, sp: *mut T) {
1095 if cfg!(debug_assertions) {
1096 let sp_raw = sp as usize;
1097 let base = self.state.stack.base() as usize;
1098 let end = base + self.state.stack.len();
1099 assert!(base <= sp_raw && sp_raw <= end);
1100 }
1101 self.state[XReg::sp].set_ptr(sp);
1102 }
1103
1104 #[must_use]
1118 unsafe fn load_ne<T, I: Encode>(&mut self, addr: impl AddressingMode) -> ControlFlow<Done, T> {
1119 unsafe { addr.load_ne::<T, I>(self) }
1120 }
1121
1122 #[must_use]
1135 unsafe fn store_ne<T, I: Encode>(
1136 &mut self,
1137 addr: impl AddressingMode,
1138 val: T,
1139 ) -> ControlFlow<Done> {
1140 unsafe { addr.store_ne::<T, I>(self, val) }
1141 }
1142
1143 fn check_xnn_from_f32<I: Encode>(
1144 &mut self,
1145 val: f32,
1146 (lo, hi): (f32, f32),
1147 ) -> ControlFlow<Done> {
1148 self.check_xnn_from_f64::<I>(val.into(), (lo.into(), hi.into()))
1149 }
1150
1151 fn check_xnn_from_f64<I: Encode>(
1152 &mut self,
1153 val: f64,
1154 (lo, hi): (f64, f64),
1155 ) -> ControlFlow<Done> {
1156 if val != val {
1157 return self.done_trap_kind::<I>(Some(TrapKind::BadConversionToInteger));
1158 }
1159 let val = val.wasm_trunc();
1160 if val <= lo || val >= hi {
1161 return self.done_trap_kind::<I>(Some(TrapKind::IntegerOverflow));
1162 }
1163 ControlFlow::Continue(())
1164 }
1165
1166 #[cfg(not(pulley_disable_interp_simd))]
1167 fn get_i128(&self, lo: XReg, hi: XReg) -> i128 {
1168 let lo = self.state[lo].get_u64();
1169 let hi = self.state[hi].get_i64();
1170 i128::from(lo) | (i128::from(hi) << 64)
1171 }
1172
1173 #[cfg(not(pulley_disable_interp_simd))]
1174 fn set_i128(&mut self, lo: XReg, hi: XReg, val: i128) {
1175 self.state[lo].set_u64(val as u64);
1176 self.state[hi].set_u64((val >> 64) as u64);
1177 }
1178
1179 fn record_executing_pc_for_profiling(&mut self) {
1180 self.executing_pc.record(self.pc.as_ptr().as_ptr() as usize);
1182 }
1183}
1184
1185trait AddressingMode: Sized {
1187 #[must_use]
1196 unsafe fn addr<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, *mut T>;
1197
1198 #[must_use]
1202 unsafe fn load_ne<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, T> {
1203 let ret = unsafe { self.addr::<T, I>(i)?.read_unaligned() };
1204 ControlFlow::Continue(ret)
1205 }
1206
1207 #[must_use]
1211 unsafe fn store_ne<T, I: Encode>(self, i: &mut Interpreter<'_>, val: T) -> ControlFlow<Done> {
1212 unsafe {
1213 self.addr::<T, I>(i)?.write_unaligned(val);
1214 }
1215 ControlFlow::Continue(())
1216 }
1217}
1218
1219impl AddressingMode for AddrO32 {
1220 unsafe fn addr<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, *mut T> {
1221 unsafe {
1225 ControlFlow::Continue(
1226 i.state[self.addr]
1227 .get_ptr::<T>()
1228 .byte_offset(self.offset as isize),
1229 )
1230 }
1231 }
1232}
1233
1234impl AddressingMode for AddrZ {
1235 unsafe fn addr<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, *mut T> {
1236 let host_addr = i.state[self.addr].get_ptr::<T>();
1239 if host_addr.is_null() {
1240 i.done_trap_kind::<I>(None)?;
1241 unreachable!();
1242 }
1243 unsafe {
1244 let addr = host_addr.byte_offset(self.offset as isize);
1245 ControlFlow::Continue(addr)
1246 }
1247 }
1248}
1249
1250impl AddressingMode for AddrG32 {
1251 unsafe fn addr<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, *mut T> {
1252 let bound = i.state[self.host_heap_bound].get_u64() as usize;
1256 let offset = usize::from(self.offset);
1257 let wasm_addr = i.state[self.wasm_addr].get_u32() as usize;
1258 if wasm_addr > bound - offset - size_of::<T>() {
1259 i.done_trap_kind::<I>(Some(TrapKind::MemoryOutOfBounds))?;
1260 unreachable!();
1261 }
1262 unsafe {
1263 let addr = i.state[self.host_heap_base]
1264 .get_ptr::<T>()
1265 .byte_add(wasm_addr)
1266 .byte_add(offset);
1267 ControlFlow::Continue(addr)
1268 }
1269 }
1270}
1271
1272impl AddressingMode for AddrG32Bne {
1273 unsafe fn addr<T, I: Encode>(self, i: &mut Interpreter<'_>) -> ControlFlow<Done, *mut T> {
1274 let bound = unsafe {
1276 *i.state[self.host_heap_bound_addr]
1277 .get_ptr::<usize>()
1278 .byte_add(usize::from(self.host_heap_bound_offset))
1279 };
1280 let wasm_addr = i.state[self.wasm_addr].get_u32() as usize;
1281 let offset = usize::from(self.offset);
1282 if wasm_addr > bound - offset - size_of::<T>() {
1283 i.done_trap_kind::<I>(Some(TrapKind::MemoryOutOfBounds))?;
1284 unreachable!();
1285 }
1286 unsafe {
1287 let addr = i.state[self.host_heap_base]
1288 .get_ptr::<T>()
1289 .byte_add(wasm_addr)
1290 .byte_add(offset);
1291 ControlFlow::Continue(addr)
1292 }
1293 }
1294}
1295
1296#[test]
1297fn simple_push_pop() {
1298 let mut state = MachineState::with_stack(16).unwrap();
1299 let pc = ExecutingPc::default();
1300 unsafe {
1301 let mut bytecode = [0; 10];
1302 let mut i = Interpreter {
1303 state: &mut state,
1304 pc: UnsafeBytecodeStream::new(NonNull::new(bytecode.as_mut_ptr().offset(4)).unwrap()),
1306 executing_pc: pc.as_ref(),
1307 };
1308 assert!(i.push::<crate::Ret, _>(0_i32).is_continue());
1309 assert_eq!(i.pop::<i32>(), 0_i32);
1310 assert!(i.push::<crate::Ret, _>(1_i32).is_continue());
1311 assert!(i.push::<crate::Ret, _>(2_i32).is_continue());
1312 assert!(i.push::<crate::Ret, _>(3_i32).is_continue());
1313 assert!(i.push::<crate::Ret, _>(4_i32).is_continue());
1314 assert!(i.push::<crate::Ret, _>(5_i32).is_break());
1315 assert!(i.push::<crate::Ret, _>(6_i32).is_break());
1316 assert_eq!(i.pop::<i32>(), 4_i32);
1317 assert_eq!(i.pop::<i32>(), 3_i32);
1318 assert_eq!(i.pop::<i32>(), 2_i32);
1319 assert_eq!(i.pop::<i32>(), 1_i32);
1320 }
1321}
1322
1323macro_rules! br_if_imm {
1324 ($(
1325 fn $snake:ident(&mut self, a: XReg, b: $imm:ident, offset: PcRelOffset)
1326 = $camel:ident / $op:tt / $get:ident;
1327 )*) => {$(
1328 fn $snake(&mut self, a: XReg, b: $imm, offset: PcRelOffset) -> ControlFlow<Done> {
1329 let a = self.state[a].$get();
1330 if a $op b.into() {
1331 self.pc_rel_jump::<crate::$camel>(offset)
1332 } else {
1333 ControlFlow::Continue(())
1334 }
1335 }
1336 )*};
1337}
1338
1339impl OpVisitor for Interpreter<'_> {
1340 type BytecodeStream = UnsafeBytecodeStream;
1341 type Return = ControlFlow<Done>;
1342
1343 fn bytecode(&mut self) -> &mut UnsafeBytecodeStream {
1344 &mut self.pc
1345 }
1346
1347 fn nop(&mut self) -> ControlFlow<Done> {
1348 ControlFlow::Continue(())
1349 }
1350
1351 fn ret(&mut self) -> ControlFlow<Done> {
1352 let lr = self.state.lr;
1353 if lr == HOST_RETURN_ADDR {
1354 self.done_return_to_host()
1355 } else {
1356 self.pc = unsafe { UnsafeBytecodeStream::new(NonNull::new_unchecked(lr)) };
1357 ControlFlow::Continue(())
1358 }
1359 }
1360
1361 fn call(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1362 let return_addr = self.pc.as_ptr();
1363 self.state.lr = return_addr.as_ptr();
1364 self.pc_rel_jump::<crate::Call>(offset)
1365 }
1366
1367 fn call1(&mut self, arg1: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1368 let return_addr = self.pc.as_ptr();
1369 self.state.lr = return_addr.as_ptr();
1370 self.state[XReg::x0] = self.state[arg1];
1371 self.pc_rel_jump::<crate::Call1>(offset)
1372 }
1373
1374 fn call2(&mut self, arg1: XReg, arg2: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1375 let return_addr = self.pc.as_ptr();
1376 self.state.lr = return_addr.as_ptr();
1377 let (x0, x1) = (self.state[arg1], self.state[arg2]);
1378 self.state[XReg::x0] = x0;
1379 self.state[XReg::x1] = x1;
1380 self.pc_rel_jump::<crate::Call2>(offset)
1381 }
1382
1383 fn call3(
1384 &mut self,
1385 arg1: XReg,
1386 arg2: XReg,
1387 arg3: XReg,
1388 offset: PcRelOffset,
1389 ) -> ControlFlow<Done> {
1390 let return_addr = self.pc.as_ptr();
1391 self.state.lr = return_addr.as_ptr();
1392 let (x0, x1, x2) = (self.state[arg1], self.state[arg2], self.state[arg3]);
1393 self.state[XReg::x0] = x0;
1394 self.state[XReg::x1] = x1;
1395 self.state[XReg::x2] = x2;
1396 self.pc_rel_jump::<crate::Call3>(offset)
1397 }
1398
1399 fn call4(
1400 &mut self,
1401 arg1: XReg,
1402 arg2: XReg,
1403 arg3: XReg,
1404 arg4: XReg,
1405 offset: PcRelOffset,
1406 ) -> ControlFlow<Done> {
1407 let return_addr = self.pc.as_ptr();
1408 self.state.lr = return_addr.as_ptr();
1409 let (x0, x1, x2, x3) = (
1410 self.state[arg1],
1411 self.state[arg2],
1412 self.state[arg3],
1413 self.state[arg4],
1414 );
1415 self.state[XReg::x0] = x0;
1416 self.state[XReg::x1] = x1;
1417 self.state[XReg::x2] = x2;
1418 self.state[XReg::x3] = x3;
1419 self.pc_rel_jump::<crate::Call4>(offset)
1420 }
1421
1422 fn call_indirect(&mut self, dst: XReg) -> ControlFlow<Done> {
1423 let return_addr = self.pc.as_ptr();
1424 self.state.lr = return_addr.as_ptr();
1425 unsafe {
1429 self.pc = UnsafeBytecodeStream::new(NonNull::new_unchecked(self.state[dst].get_ptr()));
1430 }
1431 ControlFlow::Continue(())
1432 }
1433
1434 fn jump(&mut self, offset: PcRelOffset) -> ControlFlow<Done> {
1435 self.pc_rel_jump::<crate::Jump>(offset)
1436 }
1437
1438 fn xjump(&mut self, reg: XReg) -> ControlFlow<Done> {
1439 unsafe {
1440 self.pc = UnsafeBytecodeStream::new(NonNull::new_unchecked(self.state[reg].get_ptr()));
1441 }
1442 ControlFlow::Continue(())
1443 }
1444
1445 fn br_if32(&mut self, cond: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1446 let cond = self.state[cond].get_u32();
1447 if cond != 0 {
1448 self.pc_rel_jump::<crate::BrIf>(offset)
1449 } else {
1450 ControlFlow::Continue(())
1451 }
1452 }
1453
1454 fn br_if_not32(&mut self, cond: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1455 let cond = self.state[cond].get_u32();
1456 if cond == 0 {
1457 self.pc_rel_jump::<crate::BrIfNot>(offset)
1458 } else {
1459 ControlFlow::Continue(())
1460 }
1461 }
1462
1463 fn br_if_xeq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1464 let a = self.state[a].get_u32();
1465 let b = self.state[b].get_u32();
1466 if a == b {
1467 self.pc_rel_jump::<crate::BrIfXeq32>(offset)
1468 } else {
1469 ControlFlow::Continue(())
1470 }
1471 }
1472
1473 fn br_if_xneq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1474 let a = self.state[a].get_u32();
1475 let b = self.state[b].get_u32();
1476 if a != b {
1477 self.pc_rel_jump::<crate::BrIfXneq32>(offset)
1478 } else {
1479 ControlFlow::Continue(())
1480 }
1481 }
1482
1483 fn br_if_xslt32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1484 let a = self.state[a].get_i32();
1485 let b = self.state[b].get_i32();
1486 if a < b {
1487 self.pc_rel_jump::<crate::BrIfXslt32>(offset)
1488 } else {
1489 ControlFlow::Continue(())
1490 }
1491 }
1492
1493 fn br_if_xslteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1494 let a = self.state[a].get_i32();
1495 let b = self.state[b].get_i32();
1496 if a <= b {
1497 self.pc_rel_jump::<crate::BrIfXslteq32>(offset)
1498 } else {
1499 ControlFlow::Continue(())
1500 }
1501 }
1502
1503 fn br_if_xult32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1504 let a = self.state[a].get_u32();
1505 let b = self.state[b].get_u32();
1506 if a < b {
1507 self.pc_rel_jump::<crate::BrIfXult32>(offset)
1508 } else {
1509 ControlFlow::Continue(())
1510 }
1511 }
1512
1513 fn br_if_xulteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1514 let a = self.state[a].get_u32();
1515 let b = self.state[b].get_u32();
1516 if a <= b {
1517 self.pc_rel_jump::<crate::BrIfXulteq32>(offset)
1518 } else {
1519 ControlFlow::Continue(())
1520 }
1521 }
1522
1523 fn br_if_xeq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1524 let a = self.state[a].get_u64();
1525 let b = self.state[b].get_u64();
1526 if a == b {
1527 self.pc_rel_jump::<crate::BrIfXeq64>(offset)
1528 } else {
1529 ControlFlow::Continue(())
1530 }
1531 }
1532
1533 fn br_if_xneq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1534 let a = self.state[a].get_u64();
1535 let b = self.state[b].get_u64();
1536 if a != b {
1537 self.pc_rel_jump::<crate::BrIfXneq64>(offset)
1538 } else {
1539 ControlFlow::Continue(())
1540 }
1541 }
1542
1543 fn br_if_xslt64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1544 let a = self.state[a].get_i64();
1545 let b = self.state[b].get_i64();
1546 if a < b {
1547 self.pc_rel_jump::<crate::BrIfXslt64>(offset)
1548 } else {
1549 ControlFlow::Continue(())
1550 }
1551 }
1552
1553 fn br_if_xslteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1554 let a = self.state[a].get_i64();
1555 let b = self.state[b].get_i64();
1556 if a <= b {
1557 self.pc_rel_jump::<crate::BrIfXslteq64>(offset)
1558 } else {
1559 ControlFlow::Continue(())
1560 }
1561 }
1562
1563 fn br_if_xult64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1564 let a = self.state[a].get_u64();
1565 let b = self.state[b].get_u64();
1566 if a < b {
1567 self.pc_rel_jump::<crate::BrIfXult64>(offset)
1568 } else {
1569 ControlFlow::Continue(())
1570 }
1571 }
1572
1573 fn br_if_xulteq64(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
1574 let a = self.state[a].get_u64();
1575 let b = self.state[b].get_u64();
1576 if a <= b {
1577 self.pc_rel_jump::<crate::BrIfXulteq64>(offset)
1578 } else {
1579 ControlFlow::Continue(())
1580 }
1581 }
1582
1583 br_if_imm! {
1584 fn br_if_xeq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1585 = BrIfXeq32I8 / == / get_i32;
1586 fn br_if_xeq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1587 = BrIfXeq32I32 / == / get_i32;
1588 fn br_if_xneq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1589 = BrIfXneq32I8 / != / get_i32;
1590 fn br_if_xneq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1591 = BrIfXneq32I32 / != / get_i32;
1592
1593 fn br_if_xslt32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1594 = BrIfXslt32I8 / < / get_i32;
1595 fn br_if_xslt32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1596 = BrIfXslt32I32 / < / get_i32;
1597 fn br_if_xsgt32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1598 = BrIfXsgt32I8 / > / get_i32;
1599 fn br_if_xsgt32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1600 = BrIfXsgt32I32 / > / get_i32;
1601 fn br_if_xslteq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1602 = BrIfXslteq32I8 / <= / get_i32;
1603 fn br_if_xslteq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1604 = BrIfXslteq32I32 / <= / get_i32;
1605 fn br_if_xsgteq32_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1606 = BrIfXsgteq32I8 / >= / get_i32;
1607 fn br_if_xsgteq32_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1608 = BrIfXsgteq32I32 / >= / get_i32;
1609
1610 fn br_if_xult32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1611 = BrIfXult32U8 / < / get_u32;
1612 fn br_if_xult32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1613 = BrIfXult32U32 / < / get_u32;
1614 fn br_if_xugt32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1615 = BrIfXugt32U8 / > / get_u32;
1616 fn br_if_xugt32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1617 = BrIfXugt32U32 / > / get_u32;
1618 fn br_if_xulteq32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1619 = BrIfXulteq32U8 / <= / get_u32;
1620 fn br_if_xulteq32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1621 = BrIfXulteq32U32 / <= / get_u32;
1622 fn br_if_xugteq32_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1623 = BrIfXugteq32U8 / >= / get_u32;
1624 fn br_if_xugteq32_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1625 = BrIfXugteq32U32 / >= / get_u32;
1626
1627 fn br_if_xeq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1628 = BrIfXeq64I8 / == / get_i64;
1629 fn br_if_xeq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1630 = BrIfXeq64I32 / == / get_i64;
1631 fn br_if_xneq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1632 = BrIfXneq64I8 / != / get_i64;
1633 fn br_if_xneq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1634 = BrIfXneq64I32 / != / get_i64;
1635
1636 fn br_if_xslt64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1637 = BrIfXslt64I8 / < / get_i64;
1638 fn br_if_xslt64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1639 = BrIfXslt64I32 / < / get_i64;
1640 fn br_if_xsgt64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1641 = BrIfXsgt64I8 / > / get_i64;
1642 fn br_if_xsgt64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1643 = BrIfXsgt64I32 / > / get_i64;
1644 fn br_if_xslteq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1645 = BrIfXslteq64I8 / <= / get_i64;
1646 fn br_if_xslteq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1647 = BrIfXslteq64I32 / <= / get_i64;
1648 fn br_if_xsgteq64_i8(&mut self, a: XReg, b: i8, offset: PcRelOffset)
1649 = BrIfXsgteq64I8 / >= / get_i64;
1650 fn br_if_xsgteq64_i32(&mut self, a: XReg, b: i32, offset: PcRelOffset)
1651 = BrIfXsgteq64I32 / >= / get_i64;
1652
1653 fn br_if_xult64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1654 = BrIfXult64U8 / < / get_u64;
1655 fn br_if_xult64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1656 = BrIfXult64U32 / < / get_u64;
1657 fn br_if_xugt64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1658 = BrIfXugt64U8 / > / get_u64;
1659 fn br_if_xugt64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1660 = BrIfXugt64U32 / > / get_u64;
1661 fn br_if_xulteq64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1662 = BrIfXulteq64U8 / <= / get_u64;
1663 fn br_if_xulteq64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1664 = BrIfXulteq64U32 / <= / get_u64;
1665 fn br_if_xugteq64_u8(&mut self, a: XReg, b: u8, offset: PcRelOffset)
1666 = BrIfXugteq64U8 / >= / get_u64;
1667 fn br_if_xugteq64_u32(&mut self, a: XReg, b: u32, offset: PcRelOffset)
1668 = BrIfXugteq64U32 / >= / get_u64;
1669 }
1670
1671 fn xmov(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1672 let val = self.state[src];
1673 self.state[dst] = val;
1674 ControlFlow::Continue(())
1675 }
1676
1677 fn xconst8(&mut self, dst: XReg, imm: i8) -> ControlFlow<Done> {
1678 self.state[dst].set_i64(i64::from(imm));
1679 ControlFlow::Continue(())
1680 }
1681
1682 fn xzero(&mut self, dst: XReg) -> ControlFlow<Done> {
1683 self.state[dst].set_i64(0);
1684 ControlFlow::Continue(())
1685 }
1686
1687 fn xone(&mut self, dst: XReg) -> ControlFlow<Done> {
1688 self.state[dst].set_i64(1);
1689 ControlFlow::Continue(())
1690 }
1691
1692 fn xconst16(&mut self, dst: XReg, imm: i16) -> ControlFlow<Done> {
1693 self.state[dst].set_i64(i64::from(imm));
1694 ControlFlow::Continue(())
1695 }
1696
1697 fn xconst32(&mut self, dst: XReg, imm: i32) -> ControlFlow<Done> {
1698 self.state[dst].set_i64(i64::from(imm));
1699 ControlFlow::Continue(())
1700 }
1701
1702 fn xconst64(&mut self, dst: XReg, imm: i64) -> ControlFlow<Done> {
1703 self.state[dst].set_i64(imm);
1704 ControlFlow::Continue(())
1705 }
1706
1707 fn xadd32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1708 let a = self.state[operands.src1].get_u32();
1709 let b = self.state[operands.src2].get_u32();
1710 self.state[operands.dst].set_u32(a.wrapping_add(b));
1711 ControlFlow::Continue(())
1712 }
1713
1714 fn xadd32_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1715 self.xadd32_u32(dst, src1, src2.into())
1716 }
1717
1718 fn xadd32_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1719 let a = self.state[src1].get_u32();
1720 self.state[dst].set_u32(a.wrapping_add(src2));
1721 ControlFlow::Continue(())
1722 }
1723
1724 fn xadd64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1725 let a = self.state[operands.src1].get_u64();
1726 let b = self.state[operands.src2].get_u64();
1727 self.state[operands.dst].set_u64(a.wrapping_add(b));
1728 ControlFlow::Continue(())
1729 }
1730
1731 fn xadd64_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1732 self.xadd64_u32(dst, src1, src2.into())
1733 }
1734
1735 fn xadd64_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1736 let a = self.state[src1].get_u64();
1737 self.state[dst].set_u64(a.wrapping_add(src2.into()));
1738 ControlFlow::Continue(())
1739 }
1740
1741 fn xmadd32(&mut self, dst: XReg, src1: XReg, src2: XReg, src3: XReg) -> ControlFlow<Done> {
1742 let a = self.state[src1].get_u32();
1743 let b = self.state[src2].get_u32();
1744 let c = self.state[src3].get_u32();
1745 self.state[dst].set_u32(a.wrapping_mul(b).wrapping_add(c));
1746 ControlFlow::Continue(())
1747 }
1748
1749 fn xmadd64(&mut self, dst: XReg, src1: XReg, src2: XReg, src3: XReg) -> ControlFlow<Done> {
1750 let a = self.state[src1].get_u64();
1751 let b = self.state[src2].get_u64();
1752 let c = self.state[src3].get_u64();
1753 self.state[dst].set_u64(a.wrapping_mul(b).wrapping_add(c));
1754 ControlFlow::Continue(())
1755 }
1756
1757 fn xsub32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1758 let a = self.state[operands.src1].get_u32();
1759 let b = self.state[operands.src2].get_u32();
1760 self.state[operands.dst].set_u32(a.wrapping_sub(b));
1761 ControlFlow::Continue(())
1762 }
1763
1764 fn xsub32_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1765 self.xsub32_u32(dst, src1, src2.into())
1766 }
1767
1768 fn xsub32_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1769 let a = self.state[src1].get_u32();
1770 self.state[dst].set_u32(a.wrapping_sub(src2));
1771 ControlFlow::Continue(())
1772 }
1773
1774 fn xsub64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1775 let a = self.state[operands.src1].get_u64();
1776 let b = self.state[operands.src2].get_u64();
1777 self.state[operands.dst].set_u64(a.wrapping_sub(b));
1778 ControlFlow::Continue(())
1779 }
1780
1781 fn xsub64_u8(&mut self, dst: XReg, src1: XReg, src2: u8) -> ControlFlow<Done> {
1782 self.xsub64_u32(dst, src1, src2.into())
1783 }
1784
1785 fn xsub64_u32(&mut self, dst: XReg, src1: XReg, src2: u32) -> ControlFlow<Done> {
1786 let a = self.state[src1].get_u64();
1787 self.state[dst].set_u64(a.wrapping_sub(src2.into()));
1788 ControlFlow::Continue(())
1789 }
1790
1791 fn xmul32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1792 let a = self.state[operands.src1].get_u32();
1793 let b = self.state[operands.src2].get_u32();
1794 self.state[operands.dst].set_u32(a.wrapping_mul(b));
1795 ControlFlow::Continue(())
1796 }
1797
1798 fn xmul32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
1799 self.xmul32_s32(dst, src1, src2.into())
1800 }
1801
1802 fn xmul32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
1803 let a = self.state[src1].get_i32();
1804 self.state[dst].set_i32(a.wrapping_mul(src2));
1805 ControlFlow::Continue(())
1806 }
1807
1808 fn xmul64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1809 let a = self.state[operands.src1].get_u64();
1810 let b = self.state[operands.src2].get_u64();
1811 self.state[operands.dst].set_u64(a.wrapping_mul(b));
1812 ControlFlow::Continue(())
1813 }
1814
1815 fn xmul64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
1816 self.xmul64_s32(dst, src1, src2.into())
1817 }
1818
1819 fn xmul64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
1820 let a = self.state[src1].get_i64();
1821 self.state[dst].set_i64(a.wrapping_mul(src2.into()));
1822 ControlFlow::Continue(())
1823 }
1824
1825 fn xshl32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1826 let a = self.state[operands.src1].get_u32();
1827 let b = self.state[operands.src2].get_u32();
1828 self.state[operands.dst].set_u32(a.wrapping_shl(b));
1829 ControlFlow::Continue(())
1830 }
1831
1832 fn xshr32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1833 let a = self.state[operands.src1].get_u32();
1834 let b = self.state[operands.src2].get_u32();
1835 self.state[operands.dst].set_u32(a.wrapping_shr(b));
1836 ControlFlow::Continue(())
1837 }
1838
1839 fn xshr32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1840 let a = self.state[operands.src1].get_i32();
1841 let b = self.state[operands.src2].get_u32();
1842 self.state[operands.dst].set_i32(a.wrapping_shr(b));
1843 ControlFlow::Continue(())
1844 }
1845
1846 fn xshl64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1847 let a = self.state[operands.src1].get_u64();
1848 let b = self.state[operands.src2].get_u32();
1849 self.state[operands.dst].set_u64(a.wrapping_shl(b));
1850 ControlFlow::Continue(())
1851 }
1852
1853 fn xshr64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1854 let a = self.state[operands.src1].get_u64();
1855 let b = self.state[operands.src2].get_u32();
1856 self.state[operands.dst].set_u64(a.wrapping_shr(b));
1857 ControlFlow::Continue(())
1858 }
1859
1860 fn xshr64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1861 let a = self.state[operands.src1].get_i64();
1862 let b = self.state[operands.src2].get_u32();
1863 self.state[operands.dst].set_i64(a.wrapping_shr(b));
1864 ControlFlow::Continue(())
1865 }
1866
1867 fn xshl32_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1868 let a = self.state[operands.src1].get_u32();
1869 let b = u32::from(u8::from(operands.src2));
1870 self.state[operands.dst].set_u32(a.wrapping_shl(b));
1871 ControlFlow::Continue(())
1872 }
1873
1874 fn xshr32_u_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1875 let a = self.state[operands.src1].get_u32();
1876 let b = u32::from(u8::from(operands.src2));
1877 self.state[operands.dst].set_u32(a.wrapping_shr(b));
1878 ControlFlow::Continue(())
1879 }
1880
1881 fn xshr32_s_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1882 let a = self.state[operands.src1].get_i32();
1883 let b = u32::from(u8::from(operands.src2));
1884 self.state[operands.dst].set_i32(a.wrapping_shr(b));
1885 ControlFlow::Continue(())
1886 }
1887
1888 fn xshl64_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1889 let a = self.state[operands.src1].get_u64();
1890 let b = u32::from(u8::from(operands.src2));
1891 self.state[operands.dst].set_u64(a.wrapping_shl(b));
1892 ControlFlow::Continue(())
1893 }
1894
1895 fn xshr64_u_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1896 let a = self.state[operands.src1].get_u64();
1897 let b = u32::from(u8::from(operands.src2));
1898 self.state[operands.dst].set_u64(a.wrapping_shr(b));
1899 ControlFlow::Continue(())
1900 }
1901
1902 fn xshr64_s_u6(&mut self, operands: BinaryOperands<XReg, XReg, U6>) -> ControlFlow<Done> {
1903 let a = self.state[operands.src1].get_i64();
1904 let b = u32::from(u8::from(operands.src2));
1905 self.state[operands.dst].set_i64(a.wrapping_shr(b));
1906 ControlFlow::Continue(())
1907 }
1908
1909 fn xneg32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1910 let a = self.state[src].get_i32();
1911 self.state[dst].set_i32(a.wrapping_neg());
1912 ControlFlow::Continue(())
1913 }
1914
1915 fn xneg64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
1916 let a = self.state[src].get_i64();
1917 self.state[dst].set_i64(a.wrapping_neg());
1918 ControlFlow::Continue(())
1919 }
1920
1921 fn xeq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1922 let a = self.state[operands.src1].get_u64();
1923 let b = self.state[operands.src2].get_u64();
1924 self.state[operands.dst].set_u32(u32::from(a == b));
1925 ControlFlow::Continue(())
1926 }
1927
1928 fn xneq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1929 let a = self.state[operands.src1].get_u64();
1930 let b = self.state[operands.src2].get_u64();
1931 self.state[operands.dst].set_u32(u32::from(a != b));
1932 ControlFlow::Continue(())
1933 }
1934
1935 fn xslt64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1936 let a = self.state[operands.src1].get_i64();
1937 let b = self.state[operands.src2].get_i64();
1938 self.state[operands.dst].set_u32(u32::from(a < b));
1939 ControlFlow::Continue(())
1940 }
1941
1942 fn xslteq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1943 let a = self.state[operands.src1].get_i64();
1944 let b = self.state[operands.src2].get_i64();
1945 self.state[operands.dst].set_u32(u32::from(a <= b));
1946 ControlFlow::Continue(())
1947 }
1948
1949 fn xult64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1950 let a = self.state[operands.src1].get_u64();
1951 let b = self.state[operands.src2].get_u64();
1952 self.state[operands.dst].set_u32(u32::from(a < b));
1953 ControlFlow::Continue(())
1954 }
1955
1956 fn xulteq64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1957 let a = self.state[operands.src1].get_u64();
1958 let b = self.state[operands.src2].get_u64();
1959 self.state[operands.dst].set_u32(u32::from(a <= b));
1960 ControlFlow::Continue(())
1961 }
1962
1963 fn xeq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1964 let a = self.state[operands.src1].get_u32();
1965 let b = self.state[operands.src2].get_u32();
1966 self.state[operands.dst].set_u32(u32::from(a == b));
1967 ControlFlow::Continue(())
1968 }
1969
1970 fn xneq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1971 let a = self.state[operands.src1].get_u32();
1972 let b = self.state[operands.src2].get_u32();
1973 self.state[operands.dst].set_u32(u32::from(a != b));
1974 ControlFlow::Continue(())
1975 }
1976
1977 fn xslt32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1978 let a = self.state[operands.src1].get_i32();
1979 let b = self.state[operands.src2].get_i32();
1980 self.state[operands.dst].set_u32(u32::from(a < b));
1981 ControlFlow::Continue(())
1982 }
1983
1984 fn xslteq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1985 let a = self.state[operands.src1].get_i32();
1986 let b = self.state[operands.src2].get_i32();
1987 self.state[operands.dst].set_u32(u32::from(a <= b));
1988 ControlFlow::Continue(())
1989 }
1990
1991 fn xult32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1992 let a = self.state[operands.src1].get_u32();
1993 let b = self.state[operands.src2].get_u32();
1994 self.state[operands.dst].set_u32(u32::from(a < b));
1995 ControlFlow::Continue(())
1996 }
1997
1998 fn xulteq32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
1999 let a = self.state[operands.src1].get_u32();
2000 let b = self.state[operands.src2].get_u32();
2001 self.state[operands.dst].set_u32(u32::from(a <= b));
2002 ControlFlow::Continue(())
2003 }
2004
2005 fn push_frame(&mut self) -> ControlFlow<Done> {
2006 self.push::<crate::PushFrame, _>(self.state.lr)?;
2007 self.push::<crate::PushFrame, _>(self.state.fp)?;
2008 self.state.fp = self.state[XReg::sp].get_ptr();
2009 ControlFlow::Continue(())
2010 }
2011
2012 #[inline]
2013 fn push_frame_save(&mut self, amt: u16, regs: UpperRegSet<XReg>) -> ControlFlow<Done> {
2014 let ptr_size = size_of::<usize>();
2017 let full_amt = usize::from(amt) + 2 * ptr_size;
2018 let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_sub(full_amt);
2019 self.set_sp::<crate::PushFrameSave>(new_sp)?;
2020
2021 unsafe {
2022 self.store_ne::<_, crate::PushFrameSave>(
2025 AddrO32 {
2026 addr: XReg::sp,
2027 offset: (full_amt - 1 * ptr_size) as i32,
2028 },
2029 self.state.lr,
2030 )?;
2031 self.store_ne::<_, crate::PushFrameSave>(
2032 AddrO32 {
2033 addr: XReg::sp,
2034 offset: (full_amt - 2 * ptr_size) as i32,
2035 },
2036 self.state.fp,
2037 )?;
2038
2039 let mut offset = amt as i32;
2041 self.state.fp = self.state[XReg::sp]
2042 .get_ptr::<u8>()
2043 .byte_offset(offset as isize);
2044
2045 for reg in regs {
2047 offset -= 8;
2048 self.store_ne::<_, crate::PushFrameSave>(
2049 AddrO32 {
2050 addr: XReg::sp,
2051 offset,
2052 },
2053 self.state[reg].get_u64(),
2054 )?;
2055 }
2056 }
2057 ControlFlow::Continue(())
2058 }
2059
2060 fn pop_frame_restore(&mut self, amt: u16, regs: UpperRegSet<XReg>) -> ControlFlow<Done> {
2061 unsafe {
2064 let mut offset = i32::from(amt);
2065 for reg in regs {
2066 offset -= 8;
2067 let val = self.load_ne::<_, crate::PopFrameRestore>(AddrO32 {
2068 addr: XReg::sp,
2069 offset,
2070 })?;
2071 self.state[reg].set_u64(val);
2072 }
2073 }
2074 self.pop_frame()
2075 }
2076
2077 fn pop_frame(&mut self) -> ControlFlow<Done> {
2078 self.set_sp_unchecked(self.state.fp);
2079 let fp = self.pop();
2080 let lr = self.pop();
2081 self.state.fp = fp;
2082 self.state.lr = lr;
2083 ControlFlow::Continue(())
2084 }
2085
2086 fn br_table32(&mut self, idx: XReg, amt: u32) -> ControlFlow<Done> {
2087 let idx = self.state[idx].get_u32().min(amt - 1) as isize;
2088 self.pc = unsafe { self.pc.offset(idx * 4) };
2091
2092 let mut tmp = self.pc;
2095 let Ok(rel) = PcRelOffset::decode(&mut tmp);
2096 let offset = isize::try_from(i32::from(rel)).unwrap();
2097 self.pc = unsafe { self.pc.offset(offset) };
2098 ControlFlow::Continue(())
2099 }
2100
2101 fn stack_alloc32(&mut self, amt: u32) -> ControlFlow<Done> {
2102 let amt = usize::try_from(amt).unwrap();
2103 let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_sub(amt);
2104 self.set_sp::<crate::StackAlloc32>(new_sp)?;
2105 ControlFlow::Continue(())
2106 }
2107
2108 fn stack_free32(&mut self, amt: u32) -> ControlFlow<Done> {
2109 let amt = usize::try_from(amt).unwrap();
2110 let new_sp = self.state[XReg::sp].get_ptr::<u8>().wrapping_add(amt);
2111 self.set_sp_unchecked(new_sp);
2112 ControlFlow::Continue(())
2113 }
2114
2115 fn zext8(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2116 let src = self.state[src].get_u64() as u8;
2117 self.state[dst].set_u64(src.into());
2118 ControlFlow::Continue(())
2119 }
2120
2121 fn zext16(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2122 let src = self.state[src].get_u64() as u16;
2123 self.state[dst].set_u64(src.into());
2124 ControlFlow::Continue(())
2125 }
2126
2127 fn zext32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2128 let src = self.state[src].get_u64() as u32;
2129 self.state[dst].set_u64(src.into());
2130 ControlFlow::Continue(())
2131 }
2132
2133 fn sext8(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2134 let src = self.state[src].get_i64() as i8;
2135 self.state[dst].set_i64(src.into());
2136 ControlFlow::Continue(())
2137 }
2138
2139 fn sext16(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2140 let src = self.state[src].get_i64() as i16;
2141 self.state[dst].set_i64(src.into());
2142 ControlFlow::Continue(())
2143 }
2144
2145 fn sext32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2146 let src = self.state[src].get_i64() as i32;
2147 self.state[dst].set_i64(src.into());
2148 ControlFlow::Continue(())
2149 }
2150
2151 fn xdiv32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2152 let a = self.state[operands.src1].get_i32();
2153 let b = self.state[operands.src2].get_i32();
2154 match a.checked_div(b) {
2155 Some(result) => {
2156 self.state[operands.dst].set_i32(result);
2157 ControlFlow::Continue(())
2158 }
2159 None => {
2160 let kind = if b == 0 {
2161 TrapKind::DivideByZero
2162 } else {
2163 TrapKind::IntegerOverflow
2164 };
2165 self.done_trap_kind::<crate::XDiv32S>(Some(kind))
2166 }
2167 }
2168 }
2169
2170 fn xdiv64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2171 let a = self.state[operands.src1].get_i64();
2172 let b = self.state[operands.src2].get_i64();
2173 match a.checked_div(b) {
2174 Some(result) => {
2175 self.state[operands.dst].set_i64(result);
2176 ControlFlow::Continue(())
2177 }
2178 None => {
2179 let kind = if b == 0 {
2180 TrapKind::DivideByZero
2181 } else {
2182 TrapKind::IntegerOverflow
2183 };
2184 self.done_trap_kind::<crate::XDiv64S>(Some(kind))
2185 }
2186 }
2187 }
2188
2189 fn xdiv32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2190 let a = self.state[operands.src1].get_u32();
2191 let b = self.state[operands.src2].get_u32();
2192 match a.checked_div(b) {
2193 Some(result) => {
2194 self.state[operands.dst].set_u32(result);
2195 ControlFlow::Continue(())
2196 }
2197 None => self.done_trap_kind::<crate::XDiv32U>(Some(TrapKind::DivideByZero)),
2198 }
2199 }
2200
2201 fn xdiv64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2202 let a = self.state[operands.src1].get_u64();
2203 let b = self.state[operands.src2].get_u64();
2204 match a.checked_div(b) {
2205 Some(result) => {
2206 self.state[operands.dst].set_u64(result);
2207 ControlFlow::Continue(())
2208 }
2209 None => self.done_trap_kind::<crate::XDiv64U>(Some(TrapKind::DivideByZero)),
2210 }
2211 }
2212
2213 fn xrem32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2214 let a = self.state[operands.src1].get_i32();
2215 let b = self.state[operands.src2].get_i32();
2216 let result = if a == i32::MIN && b == -1 {
2217 Some(0)
2218 } else {
2219 a.checked_rem(b)
2220 };
2221 match result {
2222 Some(result) => {
2223 self.state[operands.dst].set_i32(result);
2224 ControlFlow::Continue(())
2225 }
2226 None => self.done_trap_kind::<crate::XRem32S>(Some(TrapKind::DivideByZero)),
2227 }
2228 }
2229
2230 fn xrem64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2231 let a = self.state[operands.src1].get_i64();
2232 let b = self.state[operands.src2].get_i64();
2233 let result = if a == i64::MIN && b == -1 {
2234 Some(0)
2235 } else {
2236 a.checked_rem(b)
2237 };
2238 match result {
2239 Some(result) => {
2240 self.state[operands.dst].set_i64(result);
2241 ControlFlow::Continue(())
2242 }
2243 None => self.done_trap_kind::<crate::XRem64S>(Some(TrapKind::DivideByZero)),
2244 }
2245 }
2246
2247 fn xrem32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2248 let a = self.state[operands.src1].get_u32();
2249 let b = self.state[operands.src2].get_u32();
2250 match a.checked_rem(b) {
2251 Some(result) => {
2252 self.state[operands.dst].set_u32(result);
2253 ControlFlow::Continue(())
2254 }
2255 None => self.done_trap_kind::<crate::XRem32U>(Some(TrapKind::DivideByZero)),
2256 }
2257 }
2258
2259 fn xrem64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2260 let a = self.state[operands.src1].get_u64();
2261 let b = self.state[operands.src2].get_u64();
2262 match a.checked_rem(b) {
2263 Some(result) => {
2264 self.state[operands.dst].set_u64(result);
2265 ControlFlow::Continue(())
2266 }
2267 None => self.done_trap_kind::<crate::XRem64U>(Some(TrapKind::DivideByZero)),
2268 }
2269 }
2270
2271 fn xband32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2272 let a = self.state[operands.src1].get_u32();
2273 let b = self.state[operands.src2].get_u32();
2274 self.state[operands.dst].set_u32(a & b);
2275 ControlFlow::Continue(())
2276 }
2277
2278 fn xband32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2279 self.xband32_s32(dst, src1, src2.into())
2280 }
2281
2282 fn xband32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2283 let a = self.state[src1].get_i32();
2284 self.state[dst].set_i32(a & src2);
2285 ControlFlow::Continue(())
2286 }
2287
2288 fn xband64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2289 let a = self.state[operands.src1].get_u64();
2290 let b = self.state[operands.src2].get_u64();
2291 self.state[operands.dst].set_u64(a & b);
2292 ControlFlow::Continue(())
2293 }
2294
2295 fn xband64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2296 self.xband64_s32(dst, src1, src2.into())
2297 }
2298
2299 fn xband64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2300 let a = self.state[src1].get_i64();
2301 self.state[dst].set_i64(a & i64::from(src2));
2302 ControlFlow::Continue(())
2303 }
2304
2305 fn xbor32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2306 let a = self.state[operands.src1].get_u32();
2307 let b = self.state[operands.src2].get_u32();
2308 self.state[operands.dst].set_u32(a | b);
2309 ControlFlow::Continue(())
2310 }
2311
2312 fn xbor32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2313 self.xbor32_s32(dst, src1, src2.into())
2314 }
2315
2316 fn xbor32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2317 let a = self.state[src1].get_i32();
2318 self.state[dst].set_i32(a | src2);
2319 ControlFlow::Continue(())
2320 }
2321
2322 fn xbor64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2323 let a = self.state[operands.src1].get_u64();
2324 let b = self.state[operands.src2].get_u64();
2325 self.state[operands.dst].set_u64(a | b);
2326 ControlFlow::Continue(())
2327 }
2328
2329 fn xbor64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2330 self.xbor64_s32(dst, src1, src2.into())
2331 }
2332
2333 fn xbor64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2334 let a = self.state[src1].get_i64();
2335 self.state[dst].set_i64(a | i64::from(src2));
2336 ControlFlow::Continue(())
2337 }
2338
2339 fn xbxor32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2340 let a = self.state[operands.src1].get_u32();
2341 let b = self.state[operands.src2].get_u32();
2342 self.state[operands.dst].set_u32(a ^ b);
2343 ControlFlow::Continue(())
2344 }
2345
2346 fn xbxor32_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2347 self.xbxor32_s32(dst, src1, src2.into())
2348 }
2349
2350 fn xbxor32_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2351 let a = self.state[src1].get_i32();
2352 self.state[dst].set_i32(a ^ src2);
2353 ControlFlow::Continue(())
2354 }
2355
2356 fn xbxor64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2357 let a = self.state[operands.src1].get_u64();
2358 let b = self.state[operands.src2].get_u64();
2359 self.state[operands.dst].set_u64(a ^ b);
2360 ControlFlow::Continue(())
2361 }
2362
2363 fn xbxor64_s8(&mut self, dst: XReg, src1: XReg, src2: i8) -> ControlFlow<Done> {
2364 self.xbxor64_s32(dst, src1, src2.into())
2365 }
2366
2367 fn xbxor64_s32(&mut self, dst: XReg, src1: XReg, src2: i32) -> ControlFlow<Done> {
2368 let a = self.state[src1].get_i64();
2369 self.state[dst].set_i64(a ^ i64::from(src2));
2370 ControlFlow::Continue(())
2371 }
2372
2373 fn xbnot32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2374 let a = self.state[src].get_u32();
2375 self.state[dst].set_u32(!a);
2376 ControlFlow::Continue(())
2377 }
2378
2379 fn xbnot64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2380 let a = self.state[src].get_u64();
2381 self.state[dst].set_u64(!a);
2382 ControlFlow::Continue(())
2383 }
2384
2385 fn xmin32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2386 let a = self.state[operands.src1].get_u32();
2387 let b = self.state[operands.src2].get_u32();
2388 self.state[operands.dst].set_u32(a.min(b));
2389 ControlFlow::Continue(())
2390 }
2391
2392 fn xmin32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2393 let a = self.state[operands.src1].get_i32();
2394 let b = self.state[operands.src2].get_i32();
2395 self.state[operands.dst].set_i32(a.min(b));
2396 ControlFlow::Continue(())
2397 }
2398
2399 fn xmax32_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2400 let a = self.state[operands.src1].get_u32();
2401 let b = self.state[operands.src2].get_u32();
2402 self.state[operands.dst].set_u32(a.max(b));
2403 ControlFlow::Continue(())
2404 }
2405
2406 fn xmax32_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2407 let a = self.state[operands.src1].get_i32();
2408 let b = self.state[operands.src2].get_i32();
2409 self.state[operands.dst].set_i32(a.max(b));
2410 ControlFlow::Continue(())
2411 }
2412
2413 fn xmin64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2414 let a = self.state[operands.src1].get_u64();
2415 let b = self.state[operands.src2].get_u64();
2416 self.state[operands.dst].set_u64(a.min(b));
2417 ControlFlow::Continue(())
2418 }
2419
2420 fn xmin64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2421 let a = self.state[operands.src1].get_i64();
2422 let b = self.state[operands.src2].get_i64();
2423 self.state[operands.dst].set_i64(a.min(b));
2424 ControlFlow::Continue(())
2425 }
2426
2427 fn xmax64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2428 let a = self.state[operands.src1].get_u64();
2429 let b = self.state[operands.src2].get_u64();
2430 self.state[operands.dst].set_u64(a.max(b));
2431 ControlFlow::Continue(())
2432 }
2433
2434 fn xmax64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2435 let a = self.state[operands.src1].get_i64();
2436 let b = self.state[operands.src2].get_i64();
2437 self.state[operands.dst].set_i64(a.max(b));
2438 ControlFlow::Continue(())
2439 }
2440
2441 fn xctz32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2442 let a = self.state[src].get_u32();
2443 self.state[dst].set_u32(a.trailing_zeros());
2444 ControlFlow::Continue(())
2445 }
2446
2447 fn xctz64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2448 let a = self.state[src].get_u64();
2449 self.state[dst].set_u64(a.trailing_zeros().into());
2450 ControlFlow::Continue(())
2451 }
2452
2453 fn xclz32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2454 let a = self.state[src].get_u32();
2455 self.state[dst].set_u32(a.leading_zeros());
2456 ControlFlow::Continue(())
2457 }
2458
2459 fn xclz64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2460 let a = self.state[src].get_u64();
2461 self.state[dst].set_u64(a.leading_zeros().into());
2462 ControlFlow::Continue(())
2463 }
2464
2465 fn xpopcnt32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2466 let a = self.state[src].get_u32();
2467 self.state[dst].set_u32(a.count_ones());
2468 ControlFlow::Continue(())
2469 }
2470
2471 fn xpopcnt64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2472 let a = self.state[src].get_u64();
2473 self.state[dst].set_u64(a.count_ones().into());
2474 ControlFlow::Continue(())
2475 }
2476
2477 fn xrotl32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2478 let a = self.state[operands.src1].get_u32();
2479 let b = self.state[operands.src2].get_u32();
2480 self.state[operands.dst].set_u32(a.rotate_left(b));
2481 ControlFlow::Continue(())
2482 }
2483
2484 fn xrotl64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2485 let a = self.state[operands.src1].get_u64();
2486 let b = self.state[operands.src2].get_u32();
2487 self.state[operands.dst].set_u64(a.rotate_left(b));
2488 ControlFlow::Continue(())
2489 }
2490
2491 fn xrotr32(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2492 let a = self.state[operands.src1].get_u32();
2493 let b = self.state[operands.src2].get_u32();
2494 self.state[operands.dst].set_u32(a.rotate_right(b));
2495 ControlFlow::Continue(())
2496 }
2497
2498 fn xrotr64(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2499 let a = self.state[operands.src1].get_u64();
2500 let b = self.state[operands.src2].get_u32();
2501 self.state[operands.dst].set_u64(a.rotate_right(b));
2502 ControlFlow::Continue(())
2503 }
2504
2505 fn xselect32(
2506 &mut self,
2507 dst: XReg,
2508 cond: XReg,
2509 if_nonzero: XReg,
2510 if_zero: XReg,
2511 ) -> ControlFlow<Done> {
2512 let result = if self.state[cond].get_u32() != 0 {
2513 self.state[if_nonzero].get_u32()
2514 } else {
2515 self.state[if_zero].get_u32()
2516 };
2517 self.state[dst].set_u32(result);
2518 ControlFlow::Continue(())
2519 }
2520
2521 fn xselect64(
2522 &mut self,
2523 dst: XReg,
2524 cond: XReg,
2525 if_nonzero: XReg,
2526 if_zero: XReg,
2527 ) -> ControlFlow<Done> {
2528 let result = if self.state[cond].get_u32() != 0 {
2529 self.state[if_nonzero].get_u64()
2530 } else {
2531 self.state[if_zero].get_u64()
2532 };
2533 self.state[dst].set_u64(result);
2534 ControlFlow::Continue(())
2535 }
2536
2537 fn xabs32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2538 let a = self.state[src].get_i32();
2539 self.state[dst].set_i32(a.wrapping_abs());
2540 ControlFlow::Continue(())
2541 }
2542
2543 fn xabs64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2544 let a = self.state[src].get_i64();
2545 self.state[dst].set_i64(a.wrapping_abs());
2546 ControlFlow::Continue(())
2547 }
2548
2549 fn xload8_u32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2553 let result = unsafe { self.load_ne::<u8, crate::XLoad8U32O32>(addr)? };
2554 self.state[dst].set_u32(result.into());
2555 ControlFlow::Continue(())
2556 }
2557
2558 fn xload8_s32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2559 let result = unsafe { self.load_ne::<i8, crate::XLoad8S32O32>(addr)? };
2560 self.state[dst].set_i32(result.into());
2561 ControlFlow::Continue(())
2562 }
2563
2564 fn xload16le_u32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2565 let result = unsafe { self.load_ne::<u16, crate::XLoad16LeU32O32>(addr)? };
2566 self.state[dst].set_u32(u16::from_le(result).into());
2567 ControlFlow::Continue(())
2568 }
2569
2570 fn xload16le_s32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2571 let result = unsafe { self.load_ne::<i16, crate::XLoad16LeS32O32>(addr)? };
2572 self.state[dst].set_i32(i16::from_le(result).into());
2573 ControlFlow::Continue(())
2574 }
2575
2576 fn xload32le_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2577 let result = unsafe { self.load_ne::<i32, crate::XLoad32LeO32>(addr)? };
2578 self.state[dst].set_i32(i32::from_le(result));
2579 ControlFlow::Continue(())
2580 }
2581
2582 fn xload64le_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2583 let result = unsafe { self.load_ne::<i64, crate::XLoad64LeO32>(addr)? };
2584 self.state[dst].set_i64(i64::from_le(result));
2585 ControlFlow::Continue(())
2586 }
2587
2588 fn xstore8_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2589 let val = self.state[val].get_u32() as u8;
2590 unsafe {
2591 self.store_ne::<u8, crate::XStore8O32>(addr, val)?;
2592 }
2593 ControlFlow::Continue(())
2594 }
2595
2596 fn xstore16le_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2597 let val = self.state[val].get_u32() as u16;
2598 unsafe {
2599 self.store_ne::<u16, crate::XStore16LeO32>(addr, val.to_le())?;
2600 }
2601 ControlFlow::Continue(())
2602 }
2603
2604 fn xstore32le_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2605 let val = self.state[val].get_u32();
2606 unsafe {
2607 self.store_ne::<u32, crate::XStore32LeO32>(addr, val.to_le())?;
2608 }
2609 ControlFlow::Continue(())
2610 }
2611
2612 fn xstore64le_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2613 let val = self.state[val].get_u64();
2614 unsafe {
2615 self.store_ne::<u64, crate::XStore64LeO32>(addr, val.to_le())?;
2616 }
2617 ControlFlow::Continue(())
2618 }
2619
2620 fn xload8_u32_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2624 let result = unsafe { self.load_ne::<u8, crate::XLoad8U32G32>(addr)? };
2625 self.state[dst].set_u32(result.into());
2626 ControlFlow::Continue(())
2627 }
2628
2629 fn xload8_s32_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2630 let result = unsafe { self.load_ne::<i8, crate::XLoad8S32G32>(addr)? };
2631 self.state[dst].set_i32(result.into());
2632 ControlFlow::Continue(())
2633 }
2634
2635 fn xload16le_u32_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2636 let result = unsafe { self.load_ne::<u16, crate::XLoad16LeU32G32>(addr)? };
2637 self.state[dst].set_u32(u16::from_le(result).into());
2638 ControlFlow::Continue(())
2639 }
2640
2641 fn xload16le_s32_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2642 let result = unsafe { self.load_ne::<i16, crate::XLoad16LeS32G32>(addr)? };
2643 self.state[dst].set_i32(i16::from_le(result).into());
2644 ControlFlow::Continue(())
2645 }
2646
2647 fn xload32le_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2648 let result = unsafe { self.load_ne::<i32, crate::XLoad32LeG32>(addr)? };
2649 self.state[dst].set_i32(i32::from_le(result));
2650 ControlFlow::Continue(())
2651 }
2652
2653 fn xload64le_g32(&mut self, dst: XReg, addr: AddrG32) -> ControlFlow<Done> {
2654 let result = unsafe { self.load_ne::<i64, crate::XLoad64LeG32>(addr)? };
2655 self.state[dst].set_i64(i64::from_le(result));
2656 ControlFlow::Continue(())
2657 }
2658
2659 fn xstore8_g32(&mut self, addr: AddrG32, val: XReg) -> ControlFlow<Done> {
2660 let val = self.state[val].get_u32() as u8;
2661 unsafe {
2662 self.store_ne::<u8, crate::XStore8G32>(addr, val)?;
2663 }
2664 ControlFlow::Continue(())
2665 }
2666
2667 fn xstore16le_g32(&mut self, addr: AddrG32, val: XReg) -> ControlFlow<Done> {
2668 let val = self.state[val].get_u32() as u16;
2669 unsafe {
2670 self.store_ne::<u16, crate::XStore16LeG32>(addr, val.to_le())?;
2671 }
2672 ControlFlow::Continue(())
2673 }
2674
2675 fn xstore32le_g32(&mut self, addr: AddrG32, val: XReg) -> ControlFlow<Done> {
2676 let val = self.state[val].get_u32();
2677 unsafe {
2678 self.store_ne::<u32, crate::XStore32LeG32>(addr, val.to_le())?;
2679 }
2680 ControlFlow::Continue(())
2681 }
2682
2683 fn xstore64le_g32(&mut self, addr: AddrG32, val: XReg) -> ControlFlow<Done> {
2684 let val = self.state[val].get_u64();
2685 unsafe {
2686 self.store_ne::<u64, crate::XStore64LeG32>(addr, val.to_le())?;
2687 }
2688 ControlFlow::Continue(())
2689 }
2690
2691 fn xload8_u32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2695 let result = unsafe { self.load_ne::<u8, crate::XLoad8U32Z>(addr)? };
2696 self.state[dst].set_u32(result.into());
2697 ControlFlow::Continue(())
2698 }
2699
2700 fn xload8_s32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2701 let result = unsafe { self.load_ne::<i8, crate::XLoad8S32Z>(addr)? };
2702 self.state[dst].set_i32(result.into());
2703 ControlFlow::Continue(())
2704 }
2705
2706 fn xload16le_u32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2707 let result = unsafe { self.load_ne::<u16, crate::XLoad16LeU32Z>(addr)? };
2708 self.state[dst].set_u32(u16::from_le(result).into());
2709 ControlFlow::Continue(())
2710 }
2711
2712 fn xload16le_s32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2713 let result = unsafe { self.load_ne::<i16, crate::XLoad16LeS32Z>(addr)? };
2714 self.state[dst].set_i32(i16::from_le(result).into());
2715 ControlFlow::Continue(())
2716 }
2717
2718 fn xload32le_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2719 let result = unsafe { self.load_ne::<i32, crate::XLoad32LeZ>(addr)? };
2720 self.state[dst].set_i32(i32::from_le(result));
2721 ControlFlow::Continue(())
2722 }
2723
2724 fn xload64le_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
2725 let result = unsafe { self.load_ne::<i64, crate::XLoad64LeZ>(addr)? };
2726 self.state[dst].set_i64(i64::from_le(result));
2727 ControlFlow::Continue(())
2728 }
2729
2730 fn xstore8_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
2731 let val = self.state[val].get_u32() as u8;
2732 unsafe {
2733 self.store_ne::<u8, crate::XStore8Z>(addr, val)?;
2734 }
2735 ControlFlow::Continue(())
2736 }
2737
2738 fn xstore16le_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
2739 let val = self.state[val].get_u32() as u16;
2740 unsafe {
2741 self.store_ne::<u16, crate::XStore16LeZ>(addr, val.to_le())?;
2742 }
2743 ControlFlow::Continue(())
2744 }
2745
2746 fn xstore32le_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
2747 let val = self.state[val].get_u32();
2748 unsafe {
2749 self.store_ne::<u32, crate::XStore32LeZ>(addr, val.to_le())?;
2750 }
2751 ControlFlow::Continue(())
2752 }
2753
2754 fn xstore64le_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
2755 let val = self.state[val].get_u64();
2756 unsafe {
2757 self.store_ne::<u64, crate::XStore64LeZ>(addr, val.to_le())?;
2758 }
2759 ControlFlow::Continue(())
2760 }
2761
2762 fn xload8_u32_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2766 let result = unsafe { self.load_ne::<u8, crate::XLoad8U32G32Bne>(addr)? };
2767 self.state[dst].set_u32(result.into());
2768 ControlFlow::Continue(())
2769 }
2770
2771 fn xload8_s32_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2772 let result = unsafe { self.load_ne::<i8, crate::XLoad8S32G32Bne>(addr)? };
2773 self.state[dst].set_i32(result.into());
2774 ControlFlow::Continue(())
2775 }
2776
2777 fn xload16le_u32_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2778 let result = unsafe { self.load_ne::<u16, crate::XLoad16LeU32G32Bne>(addr)? };
2779 self.state[dst].set_u32(u16::from_le(result).into());
2780 ControlFlow::Continue(())
2781 }
2782
2783 fn xload16le_s32_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2784 let result = unsafe { self.load_ne::<i16, crate::XLoad16LeS32G32Bne>(addr)? };
2785 self.state[dst].set_i32(i16::from_le(result).into());
2786 ControlFlow::Continue(())
2787 }
2788
2789 fn xload32le_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2790 let result = unsafe { self.load_ne::<i32, crate::XLoad32LeG32Bne>(addr)? };
2791 self.state[dst].set_i32(i32::from_le(result));
2792 ControlFlow::Continue(())
2793 }
2794
2795 fn xload64le_g32bne(&mut self, dst: XReg, addr: AddrG32Bne) -> ControlFlow<Done> {
2796 let result = unsafe { self.load_ne::<i64, crate::XLoad64LeG32Bne>(addr)? };
2797 self.state[dst].set_i64(i64::from_le(result));
2798 ControlFlow::Continue(())
2799 }
2800
2801 fn xstore8_g32bne(&mut self, addr: AddrG32Bne, val: XReg) -> ControlFlow<Done> {
2802 let val = self.state[val].get_u32() as u8;
2803 unsafe {
2804 self.store_ne::<u8, crate::XStore8G32Bne>(addr, val)?;
2805 }
2806 ControlFlow::Continue(())
2807 }
2808
2809 fn xstore16le_g32bne(&mut self, addr: AddrG32Bne, val: XReg) -> ControlFlow<Done> {
2810 let val = self.state[val].get_u32() as u16;
2811 unsafe {
2812 self.store_ne::<u16, crate::XStore16LeG32Bne>(addr, val.to_le())?;
2813 }
2814 ControlFlow::Continue(())
2815 }
2816
2817 fn xstore32le_g32bne(&mut self, addr: AddrG32Bne, val: XReg) -> ControlFlow<Done> {
2818 let val = self.state[val].get_u32();
2819 unsafe {
2820 self.store_ne::<u32, crate::XStore32LeG32Bne>(addr, val.to_le())?;
2821 }
2822 ControlFlow::Continue(())
2823 }
2824
2825 fn xstore64le_g32bne(&mut self, addr: AddrG32Bne, val: XReg) -> ControlFlow<Done> {
2826 let val = self.state[val].get_u64();
2827 unsafe {
2828 self.store_ne::<u64, crate::XStore64LeG32Bne>(addr, val.to_le())?;
2829 }
2830 ControlFlow::Continue(())
2831 }
2832}
2833
2834impl ExtendedOpVisitor for Interpreter<'_> {
2835 fn trap(&mut self) -> ControlFlow<Done> {
2836 self.done_trap::<crate::Trap>()
2837 }
2838
2839 fn call_indirect_host(&mut self, id: u8) -> ControlFlow<Done> {
2840 self.done_call_indirect_host(id)
2841 }
2842
2843 fn xpcadd(&mut self, dst: XReg, offset: PcRelOffset) -> ControlFlow<Done> {
2844 let pc = self.pc_rel::<crate::Xpcadd>(offset);
2845 self.state[dst].set_ptr(pc.as_ptr());
2846 ControlFlow::Continue(())
2847 }
2848
2849 fn bswap32(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2850 let src = self.state[src].get_u32();
2851 self.state[dst].set_u32(src.swap_bytes());
2852 ControlFlow::Continue(())
2853 }
2854
2855 fn bswap64(&mut self, dst: XReg, src: XReg) -> ControlFlow<Done> {
2856 let src = self.state[src].get_u64();
2857 self.state[dst].set_u64(src.swap_bytes());
2858 ControlFlow::Continue(())
2859 }
2860
2861 fn xbmask32(&mut self, dst: XReg, src: XReg) -> Self::Return {
2862 let a = self.state[src].get_u32();
2863 if a == 0 {
2864 self.state[dst].set_u32(0);
2865 } else {
2866 self.state[dst].set_i32(-1);
2867 }
2868 ControlFlow::Continue(())
2869 }
2870
2871 fn xbmask64(&mut self, dst: XReg, src: XReg) -> Self::Return {
2872 let a = self.state[src].get_u64();
2873 if a == 0 {
2874 self.state[dst].set_u64(0);
2875 } else {
2876 self.state[dst].set_i64(-1);
2877 }
2878 ControlFlow::Continue(())
2879 }
2880
2881 fn xadd32_uoverflow_trap(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2882 let a = self.state[operands.src1].get_u32();
2883 let b = self.state[operands.src2].get_u32();
2884 match a.checked_add(b) {
2885 Some(c) => {
2886 self.state[operands.dst].set_u32(c);
2887 ControlFlow::Continue(())
2888 }
2889 None => self.done_trap::<crate::Xadd32UoverflowTrap>(),
2890 }
2891 }
2892
2893 fn xadd64_uoverflow_trap(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2894 let a = self.state[operands.src1].get_u64();
2895 let b = self.state[operands.src2].get_u64();
2896 match a.checked_add(b) {
2897 Some(c) => {
2898 self.state[operands.dst].set_u64(c);
2899 ControlFlow::Continue(())
2900 }
2901 None => self.done_trap::<crate::Xadd64UoverflowTrap>(),
2902 }
2903 }
2904
2905 fn xmulhi64_s(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2906 let a = self.state[operands.src1].get_i64();
2907 let b = self.state[operands.src2].get_i64();
2908 let result = ((i128::from(a) * i128::from(b)) >> 64) as i64;
2909 self.state[operands.dst].set_i64(result);
2910 ControlFlow::Continue(())
2911 }
2912
2913 fn xmulhi64_u(&mut self, operands: BinaryOperands<XReg>) -> ControlFlow<Done> {
2914 let a = self.state[operands.src1].get_u64();
2915 let b = self.state[operands.src2].get_u64();
2916 let result = ((u128::from(a) * u128::from(b)) >> 64) as u64;
2917 self.state[operands.dst].set_u64(result);
2918 ControlFlow::Continue(())
2919 }
2920
2921 fn xload16be_u32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2925 let result = unsafe { self.load_ne::<u16, crate::XLoad16BeU32O32>(addr)? };
2926 self.state[dst].set_u32(u16::from_be(result).into());
2927 ControlFlow::Continue(())
2928 }
2929
2930 fn xload16be_s32_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2931 let result = unsafe { self.load_ne::<i16, crate::XLoad16BeS32O32>(addr)? };
2932 self.state[dst].set_i32(i16::from_be(result).into());
2933 ControlFlow::Continue(())
2934 }
2935
2936 fn xload32be_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2937 let result = unsafe { self.load_ne::<i32, crate::XLoad32BeO32>(addr)? };
2938 self.state[dst].set_i32(i32::from_be(result));
2939 ControlFlow::Continue(())
2940 }
2941
2942 fn xload64be_o32(&mut self, dst: XReg, addr: AddrO32) -> ControlFlow<Done> {
2943 let result = unsafe { self.load_ne::<i64, crate::XLoad64BeO32>(addr)? };
2944 self.state[dst].set_i64(i64::from_be(result));
2945 ControlFlow::Continue(())
2946 }
2947
2948 fn xstore16be_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2949 let val = self.state[val].get_u32() as u16;
2950 unsafe {
2951 self.store_ne::<u16, crate::XStore16BeO32>(addr, val.to_be())?;
2952 }
2953 ControlFlow::Continue(())
2954 }
2955
2956 fn xstore32be_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2957 let val = self.state[val].get_u32();
2958 unsafe {
2959 self.store_ne::<u32, crate::XStore32BeO32>(addr, val.to_be())?;
2960 }
2961 ControlFlow::Continue(())
2962 }
2963
2964 fn xstore64be_o32(&mut self, addr: AddrO32, val: XReg) -> ControlFlow<Done> {
2965 let val = self.state[val].get_u64();
2966 unsafe {
2967 self.store_ne::<u64, crate::XStore64BeO32>(addr, val.to_be())?;
2968 }
2969 ControlFlow::Continue(())
2970 }
2971
2972 fn fload32le_o32(&mut self, dst: FReg, addr: AddrO32) -> ControlFlow<Done> {
2976 let val = unsafe { self.load_ne::<u32, crate::Fload32LeO32>(addr)? };
2977 self.state[dst].set_f32(f32::from_bits(u32::from_le(val)));
2978 ControlFlow::Continue(())
2979 }
2980
2981 fn fload64le_o32(&mut self, dst: FReg, addr: AddrO32) -> ControlFlow<Done> {
2982 let val = unsafe { self.load_ne::<u64, crate::Fload64LeO32>(addr)? };
2983 self.state[dst].set_f64(f64::from_bits(u64::from_le(val)));
2984 ControlFlow::Continue(())
2985 }
2986
2987 fn fstore32le_o32(&mut self, addr: AddrO32, src: FReg) -> ControlFlow<Done> {
2988 let val = self.state[src].get_f32();
2989 unsafe {
2990 self.store_ne::<u32, crate::Fstore32LeO32>(addr, val.to_bits().to_le())?;
2991 }
2992 ControlFlow::Continue(())
2993 }
2994
2995 fn fstore64le_o32(&mut self, addr: AddrO32, src: FReg) -> ControlFlow<Done> {
2996 let val = self.state[src].get_f64();
2997 unsafe {
2998 self.store_ne::<u64, crate::Fstore64LeO32>(addr, val.to_bits().to_le())?;
2999 }
3000 ControlFlow::Continue(())
3001 }
3002
3003 fn fload32be_o32(&mut self, dst: FReg, addr: AddrO32) -> ControlFlow<Done> {
3007 let val = unsafe { self.load_ne::<u32, crate::Fload32BeO32>(addr)? };
3008 self.state[dst].set_f32(f32::from_bits(u32::from_be(val)));
3009 ControlFlow::Continue(())
3010 }
3011
3012 fn fload64be_o32(&mut self, dst: FReg, addr: AddrO32) -> ControlFlow<Done> {
3013 let val = unsafe { self.load_ne::<u64, crate::Fload64BeO32>(addr)? };
3014 self.state[dst].set_f64(f64::from_bits(u64::from_be(val)));
3015 ControlFlow::Continue(())
3016 }
3017
3018 fn fstore32be_o32(&mut self, addr: AddrO32, src: FReg) -> ControlFlow<Done> {
3019 let val = self.state[src].get_f32();
3020 unsafe {
3021 self.store_ne::<u32, crate::Fstore32BeO32>(addr, val.to_bits().to_be())?;
3022 }
3023 ControlFlow::Continue(())
3024 }
3025
3026 fn fstore64be_o32(&mut self, addr: AddrO32, src: FReg) -> ControlFlow<Done> {
3027 let val = self.state[src].get_f64();
3028 unsafe {
3029 self.store_ne::<u64, crate::Fstore64BeO32>(addr, val.to_bits().to_be())?;
3030 }
3031 ControlFlow::Continue(())
3032 }
3033
3034 fn fload32le_z(&mut self, dst: FReg, addr: AddrZ) -> ControlFlow<Done> {
3038 let val = unsafe { self.load_ne::<u32, crate::Fload32LeZ>(addr)? };
3039 self.state[dst].set_f32(f32::from_bits(u32::from_le(val)));
3040 ControlFlow::Continue(())
3041 }
3042
3043 fn fload64le_z(&mut self, dst: FReg, addr: AddrZ) -> ControlFlow<Done> {
3044 let val = unsafe { self.load_ne::<u64, crate::Fload64LeZ>(addr)? };
3045 self.state[dst].set_f64(f64::from_bits(u64::from_le(val)));
3046 ControlFlow::Continue(())
3047 }
3048
3049 fn fstore32le_z(&mut self, addr: AddrZ, src: FReg) -> ControlFlow<Done> {
3050 let val = self.state[src].get_f32();
3051 unsafe {
3052 self.store_ne::<u32, crate::Fstore32LeZ>(addr, val.to_bits().to_le())?;
3053 }
3054 ControlFlow::Continue(())
3055 }
3056
3057 fn fstore64le_z(&mut self, addr: AddrZ, src: FReg) -> ControlFlow<Done> {
3058 let val = self.state[src].get_f64();
3059 unsafe {
3060 self.store_ne::<u64, crate::Fstore64LeZ>(addr, val.to_bits().to_le())?;
3061 }
3062 ControlFlow::Continue(())
3063 }
3064
3065 fn fload32le_g32(&mut self, dst: FReg, addr: AddrG32) -> ControlFlow<Done> {
3069 let val = unsafe { self.load_ne::<u32, crate::Fload32LeG32>(addr)? };
3070 self.state[dst].set_f32(f32::from_bits(u32::from_le(val)));
3071 ControlFlow::Continue(())
3072 }
3073
3074 fn fload64le_g32(&mut self, dst: FReg, addr: AddrG32) -> ControlFlow<Done> {
3075 let val = unsafe { self.load_ne::<u64, crate::Fload64LeG32>(addr)? };
3076 self.state[dst].set_f64(f64::from_bits(u64::from_le(val)));
3077 ControlFlow::Continue(())
3078 }
3079
3080 fn fstore32le_g32(&mut self, addr: AddrG32, src: FReg) -> ControlFlow<Done> {
3081 let val = self.state[src].get_f32();
3082 unsafe {
3083 self.store_ne::<u32, crate::Fstore32LeG32>(addr, val.to_bits().to_le())?;
3084 }
3085 ControlFlow::Continue(())
3086 }
3087
3088 fn fstore64le_g32(&mut self, addr: AddrG32, src: FReg) -> ControlFlow<Done> {
3089 let val = self.state[src].get_f64();
3090 unsafe {
3091 self.store_ne::<u64, crate::Fstore64LeG32>(addr, val.to_bits().to_le())?;
3092 }
3093 ControlFlow::Continue(())
3094 }
3095
3096 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3100 fn vload128le_o32(&mut self, dst: VReg, addr: AddrO32) -> ControlFlow<Done> {
3101 let val = unsafe { self.load_ne::<u128, crate::VLoad128O32>(addr)? };
3102 self.state[dst].set_u128(u128::from_le(val));
3103 ControlFlow::Continue(())
3104 }
3105
3106 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3107 fn vstore128le_o32(&mut self, addr: AddrO32, src: VReg) -> ControlFlow<Done> {
3108 let val = self.state[src].get_u128();
3109 unsafe {
3110 self.store_ne::<u128, crate::Vstore128LeO32>(addr, val.to_le())?;
3111 }
3112 ControlFlow::Continue(())
3113 }
3114
3115 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3119 fn vload128le_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
3120 let val = unsafe { self.load_ne::<u128, crate::VLoad128LeZ>(addr)? };
3121 self.state[dst].set_u128(u128::from_le(val));
3122 ControlFlow::Continue(())
3123 }
3124
3125 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3126 fn vstore128le_z(&mut self, addr: AddrZ, src: VReg) -> ControlFlow<Done> {
3127 let val = self.state[src].get_u128();
3128 unsafe {
3129 self.store_ne::<u128, crate::Vstore128LeZ>(addr, val.to_le())?;
3130 }
3131 ControlFlow::Continue(())
3132 }
3133
3134 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3138 fn vload128le_g32(&mut self, dst: VReg, addr: AddrG32) -> ControlFlow<Done> {
3139 let val = unsafe { self.load_ne::<u128, crate::VLoad128G32>(addr)? };
3140 self.state[dst].set_u128(u128::from_le(val));
3141 ControlFlow::Continue(())
3142 }
3143
3144 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3145 fn vstore128le_g32(&mut self, addr: AddrG32, src: VReg) -> ControlFlow<Done> {
3146 let val = self.state[src].get_u128();
3147 unsafe {
3148 self.store_ne::<u128, crate::Vstore128LeG32>(addr, val.to_le())?;
3149 }
3150 ControlFlow::Continue(())
3151 }
3152
3153 fn xmov_fp(&mut self, dst: XReg) -> ControlFlow<Done> {
3154 let fp = self.state.fp;
3155 self.state[dst].set_ptr(fp);
3156 ControlFlow::Continue(())
3157 }
3158
3159 fn xmov_lr(&mut self, dst: XReg) -> ControlFlow<Done> {
3160 let lr = self.state.lr;
3161 self.state[dst].set_ptr(lr);
3162 ControlFlow::Continue(())
3163 }
3164
3165 fn fmov(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3166 let val = self.state[src];
3167 self.state[dst] = val;
3168 ControlFlow::Continue(())
3169 }
3170
3171 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3172 fn vmov(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3173 let val = self.state[src];
3174 self.state[dst] = val;
3175 ControlFlow::Continue(())
3176 }
3177
3178 fn fconst32(&mut self, dst: FReg, bits: u32) -> ControlFlow<Done> {
3179 self.state[dst].set_f32(f32::from_bits(bits));
3180 ControlFlow::Continue(())
3181 }
3182
3183 fn fconst64(&mut self, dst: FReg, bits: u64) -> ControlFlow<Done> {
3184 self.state[dst].set_f64(f64::from_bits(bits));
3185 ControlFlow::Continue(())
3186 }
3187
3188 fn bitcast_int_from_float_32(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3189 let val = self.state[src].get_f32();
3190 self.state[dst].set_u32(val.to_bits());
3191 ControlFlow::Continue(())
3192 }
3193
3194 fn bitcast_int_from_float_64(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3195 let val = self.state[src].get_f64();
3196 self.state[dst].set_u64(val.to_bits());
3197 ControlFlow::Continue(())
3198 }
3199
3200 fn bitcast_float_from_int_32(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3201 let val = self.state[src].get_u32();
3202 self.state[dst].set_f32(f32::from_bits(val));
3203 ControlFlow::Continue(())
3204 }
3205
3206 fn bitcast_float_from_int_64(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3207 let val = self.state[src].get_u64();
3208 self.state[dst].set_f64(f64::from_bits(val));
3209 ControlFlow::Continue(())
3210 }
3211
3212 fn feq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3213 let a = self.state[src1].get_f32();
3214 let b = self.state[src2].get_f32();
3215 self.state[dst].set_u32(u32::from(a == b));
3216 ControlFlow::Continue(())
3217 }
3218
3219 fn fneq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3220 let a = self.state[src1].get_f32();
3221 let b = self.state[src2].get_f32();
3222 self.state[dst].set_u32(u32::from(a != b));
3223 ControlFlow::Continue(())
3224 }
3225
3226 fn flt32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3227 let a = self.state[src1].get_f32();
3228 let b = self.state[src2].get_f32();
3229 self.state[dst].set_u32(u32::from(a < b));
3230 ControlFlow::Continue(())
3231 }
3232
3233 fn flteq32(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3234 let a = self.state[src1].get_f32();
3235 let b = self.state[src2].get_f32();
3236 self.state[dst].set_u32(u32::from(a <= b));
3237 ControlFlow::Continue(())
3238 }
3239
3240 fn feq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3241 let a = self.state[src1].get_f64();
3242 let b = self.state[src2].get_f64();
3243 self.state[dst].set_u32(u32::from(a == b));
3244 ControlFlow::Continue(())
3245 }
3246
3247 fn fneq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3248 let a = self.state[src1].get_f64();
3249 let b = self.state[src2].get_f64();
3250 self.state[dst].set_u32(u32::from(a != b));
3251 ControlFlow::Continue(())
3252 }
3253
3254 fn flt64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3255 let a = self.state[src1].get_f64();
3256 let b = self.state[src2].get_f64();
3257 self.state[dst].set_u32(u32::from(a < b));
3258 ControlFlow::Continue(())
3259 }
3260
3261 fn flteq64(&mut self, dst: XReg, src1: FReg, src2: FReg) -> ControlFlow<Done> {
3262 let a = self.state[src1].get_f64();
3263 let b = self.state[src2].get_f64();
3264 self.state[dst].set_u32(u32::from(a <= b));
3265 ControlFlow::Continue(())
3266 }
3267
3268 fn fselect32(
3269 &mut self,
3270 dst: FReg,
3271 cond: XReg,
3272 if_nonzero: FReg,
3273 if_zero: FReg,
3274 ) -> ControlFlow<Done> {
3275 let result = if self.state[cond].get_u32() != 0 {
3276 self.state[if_nonzero].get_f32()
3277 } else {
3278 self.state[if_zero].get_f32()
3279 };
3280 self.state[dst].set_f32(result);
3281 ControlFlow::Continue(())
3282 }
3283
3284 fn fselect64(
3285 &mut self,
3286 dst: FReg,
3287 cond: XReg,
3288 if_nonzero: FReg,
3289 if_zero: FReg,
3290 ) -> ControlFlow<Done> {
3291 let result = if self.state[cond].get_u32() != 0 {
3292 self.state[if_nonzero].get_f64()
3293 } else {
3294 self.state[if_zero].get_f64()
3295 };
3296 self.state[dst].set_f64(result);
3297 ControlFlow::Continue(())
3298 }
3299
3300 fn f32_from_x32_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3301 let a = self.state[src].get_i32();
3302 self.state[dst].set_f32(a as f32);
3303 ControlFlow::Continue(())
3304 }
3305
3306 fn f32_from_x32_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3307 let a = self.state[src].get_u32();
3308 self.state[dst].set_f32(a as f32);
3309 ControlFlow::Continue(())
3310 }
3311
3312 fn f32_from_x64_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3313 let a = self.state[src].get_i64();
3314 self.state[dst].set_f32(a as f32);
3315 ControlFlow::Continue(())
3316 }
3317
3318 fn f32_from_x64_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3319 let a = self.state[src].get_u64();
3320 self.state[dst].set_f32(a as f32);
3321 ControlFlow::Continue(())
3322 }
3323
3324 fn f64_from_x32_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3325 let a = self.state[src].get_i32();
3326 self.state[dst].set_f64(a as f64);
3327 ControlFlow::Continue(())
3328 }
3329
3330 fn f64_from_x32_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3331 let a = self.state[src].get_u32();
3332 self.state[dst].set_f64(a as f64);
3333 ControlFlow::Continue(())
3334 }
3335
3336 fn f64_from_x64_s(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3337 let a = self.state[src].get_i64();
3338 self.state[dst].set_f64(a as f64);
3339 ControlFlow::Continue(())
3340 }
3341
3342 fn f64_from_x64_u(&mut self, dst: FReg, src: XReg) -> ControlFlow<Done> {
3343 let a = self.state[src].get_u64();
3344 self.state[dst].set_f64(a as f64);
3345 ControlFlow::Continue(())
3346 }
3347
3348 fn x32_from_f32_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3349 let a = self.state[src].get_f32();
3350 self.check_xnn_from_f32::<crate::X32FromF32S>(a, f32_cvt_to_int_bounds(true, 32))?;
3351 self.state[dst].set_i32(a as i32);
3352 ControlFlow::Continue(())
3353 }
3354
3355 fn x32_from_f32_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3356 let a = self.state[src].get_f32();
3357 self.check_xnn_from_f32::<crate::X32FromF32U>(a, f32_cvt_to_int_bounds(false, 32))?;
3358 self.state[dst].set_u32(a as u32);
3359 ControlFlow::Continue(())
3360 }
3361
3362 fn x64_from_f32_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3363 let a = self.state[src].get_f32();
3364 self.check_xnn_from_f32::<crate::X64FromF32S>(a, f32_cvt_to_int_bounds(true, 64))?;
3365 self.state[dst].set_i64(a as i64);
3366 ControlFlow::Continue(())
3367 }
3368
3369 fn x64_from_f32_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3370 let a = self.state[src].get_f32();
3371 self.check_xnn_from_f32::<crate::X64FromF32U>(a, f32_cvt_to_int_bounds(false, 64))?;
3372 self.state[dst].set_u64(a as u64);
3373 ControlFlow::Continue(())
3374 }
3375
3376 fn x32_from_f64_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3377 let a = self.state[src].get_f64();
3378 self.check_xnn_from_f64::<crate::X32FromF64S>(a, f64_cvt_to_int_bounds(true, 32))?;
3379 self.state[dst].set_i32(a as i32);
3380 ControlFlow::Continue(())
3381 }
3382
3383 fn x32_from_f64_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3384 let a = self.state[src].get_f64();
3385 self.check_xnn_from_f64::<crate::X32FromF64U>(a, f64_cvt_to_int_bounds(false, 32))?;
3386 self.state[dst].set_u32(a as u32);
3387 ControlFlow::Continue(())
3388 }
3389
3390 fn x64_from_f64_s(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3391 let a = self.state[src].get_f64();
3392 self.check_xnn_from_f64::<crate::X64FromF64S>(a, f64_cvt_to_int_bounds(true, 64))?;
3393 self.state[dst].set_i64(a as i64);
3394 ControlFlow::Continue(())
3395 }
3396
3397 fn x64_from_f64_u(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3398 let a = self.state[src].get_f64();
3399 self.check_xnn_from_f64::<crate::X64FromF64U>(a, f64_cvt_to_int_bounds(false, 64))?;
3400 self.state[dst].set_u64(a as u64);
3401 ControlFlow::Continue(())
3402 }
3403
3404 fn x32_from_f32_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3405 let a = self.state[src].get_f32();
3406 self.state[dst].set_i32(a as i32);
3407 ControlFlow::Continue(())
3408 }
3409
3410 fn x32_from_f32_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3411 let a = self.state[src].get_f32();
3412 self.state[dst].set_u32(a as u32);
3413 ControlFlow::Continue(())
3414 }
3415
3416 fn x64_from_f32_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3417 let a = self.state[src].get_f32();
3418 self.state[dst].set_i64(a as i64);
3419 ControlFlow::Continue(())
3420 }
3421
3422 fn x64_from_f32_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3423 let a = self.state[src].get_f32();
3424 self.state[dst].set_u64(a as u64);
3425 ControlFlow::Continue(())
3426 }
3427
3428 fn x32_from_f64_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3429 let a = self.state[src].get_f64();
3430 self.state[dst].set_i32(a as i32);
3431 ControlFlow::Continue(())
3432 }
3433
3434 fn x32_from_f64_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3435 let a = self.state[src].get_f64();
3436 self.state[dst].set_u32(a as u32);
3437 ControlFlow::Continue(())
3438 }
3439
3440 fn x64_from_f64_s_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3441 let a = self.state[src].get_f64();
3442 self.state[dst].set_i64(a as i64);
3443 ControlFlow::Continue(())
3444 }
3445
3446 fn x64_from_f64_u_sat(&mut self, dst: XReg, src: FReg) -> ControlFlow<Done> {
3447 let a = self.state[src].get_f64();
3448 self.state[dst].set_u64(a as u64);
3449 ControlFlow::Continue(())
3450 }
3451
3452 fn f32_from_f64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3453 let a = self.state[src].get_f64();
3454 self.state[dst].set_f32(a as f32);
3455 ControlFlow::Continue(())
3456 }
3457
3458 fn f64_from_f32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3459 let a = self.state[src].get_f32();
3460 self.state[dst].set_f64(a.into());
3461 ControlFlow::Continue(())
3462 }
3463
3464 fn fcopysign32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3465 let a = self.state[operands.src1].get_f32();
3466 let b = self.state[operands.src2].get_f32();
3467 self.state[operands.dst].set_f32(a.wasm_copysign(b));
3468 ControlFlow::Continue(())
3469 }
3470
3471 fn fcopysign64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3472 let a = self.state[operands.src1].get_f64();
3473 let b = self.state[operands.src2].get_f64();
3474 self.state[operands.dst].set_f64(a.wasm_copysign(b));
3475 ControlFlow::Continue(())
3476 }
3477
3478 fn fadd32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3479 let a = self.state[operands.src1].get_f32();
3480 let b = self.state[operands.src2].get_f32();
3481 self.state[operands.dst].set_f32(a + b);
3482 ControlFlow::Continue(())
3483 }
3484
3485 fn fsub32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3486 let a = self.state[operands.src1].get_f32();
3487 let b = self.state[operands.src2].get_f32();
3488 self.state[operands.dst].set_f32(a - b);
3489 ControlFlow::Continue(())
3490 }
3491
3492 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3493 fn vsubf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3494 let mut a = self.state[operands.src1].get_f32x4();
3495 let b = self.state[operands.src2].get_f32x4();
3496 for (a, b) in a.iter_mut().zip(b) {
3497 *a = *a - b;
3498 }
3499 self.state[operands.dst].set_f32x4(a);
3500 ControlFlow::Continue(())
3501 }
3502
3503 fn fmul32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3504 let a = self.state[operands.src1].get_f32();
3505 let b = self.state[operands.src2].get_f32();
3506 self.state[operands.dst].set_f32(a * b);
3507 ControlFlow::Continue(())
3508 }
3509
3510 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3511 fn vmulf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3512 let mut a = self.state[operands.src1].get_f32x4();
3513 let b = self.state[operands.src2].get_f32x4();
3514 for (a, b) in a.iter_mut().zip(b) {
3515 *a = *a * b;
3516 }
3517 self.state[operands.dst].set_f32x4(a);
3518 ControlFlow::Continue(())
3519 }
3520
3521 fn fdiv32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3522 let a = self.state[operands.src1].get_f32();
3523 let b = self.state[operands.src2].get_f32();
3524 self.state[operands.dst].set_f32(a / b);
3525 ControlFlow::Continue(())
3526 }
3527
3528 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3529 fn vdivf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3530 let a = self.state[operands.src1].get_f32x4();
3531 let b = self.state[operands.src2].get_f32x4();
3532 let mut result = [0.0f32; 4];
3533
3534 for i in 0..4 {
3535 result[i] = a[i] / b[i];
3536 }
3537
3538 self.state[operands.dst].set_f32x4(result);
3539 ControlFlow::Continue(())
3540 }
3541
3542 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3543 fn vdivf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3544 let a = self.state[operands.src1].get_f64x2();
3545 let b = self.state[operands.src2].get_f64x2();
3546 let mut result = [0.0f64; 2];
3547
3548 for i in 0..2 {
3549 result[i] = a[i] / b[i];
3550 }
3551
3552 self.state[operands.dst].set_f64x2(result);
3553 ControlFlow::Continue(())
3554 }
3555
3556 fn fmaximum32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3557 let a = self.state[operands.src1].get_f32();
3558 let b = self.state[operands.src2].get_f32();
3559 self.state[operands.dst].set_f32(a.wasm_maximum(b));
3560 ControlFlow::Continue(())
3561 }
3562
3563 fn fminimum32(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3564 let a = self.state[operands.src1].get_f32();
3565 let b = self.state[operands.src2].get_f32();
3566 self.state[operands.dst].set_f32(a.wasm_minimum(b));
3567 ControlFlow::Continue(())
3568 }
3569
3570 fn ftrunc32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3571 let a = self.state[src].get_f32();
3572 self.state[dst].set_f32(a.wasm_trunc());
3573 ControlFlow::Continue(())
3574 }
3575
3576 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3577 fn vtrunc32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3578 let mut a = self.state[src].get_f32x4();
3579 for elem in a.iter_mut() {
3580 *elem = elem.wasm_trunc();
3581 }
3582 self.state[dst].set_f32x4(a);
3583 ControlFlow::Continue(())
3584 }
3585
3586 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3587 fn vtrunc64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3588 let mut a = self.state[src].get_f64x2();
3589 for elem in a.iter_mut() {
3590 *elem = elem.wasm_trunc();
3591 }
3592 self.state[dst].set_f64x2(a);
3593 ControlFlow::Continue(())
3594 }
3595
3596 fn ffloor32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3597 let a = self.state[src].get_f32();
3598 self.state[dst].set_f32(a.wasm_floor());
3599 ControlFlow::Continue(())
3600 }
3601
3602 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3603 fn vfloor32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3604 let mut a = self.state[src].get_f32x4();
3605 for elem in a.iter_mut() {
3606 *elem = elem.wasm_floor();
3607 }
3608 self.state[dst].set_f32x4(a);
3609 ControlFlow::Continue(())
3610 }
3611
3612 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3613 fn vfloor64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3614 let mut a = self.state[src].get_f64x2();
3615 for elem in a.iter_mut() {
3616 *elem = elem.wasm_floor();
3617 }
3618 self.state[dst].set_f64x2(a);
3619 ControlFlow::Continue(())
3620 }
3621
3622 fn fceil32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3623 let a = self.state[src].get_f32();
3624 self.state[dst].set_f32(a.wasm_ceil());
3625 ControlFlow::Continue(())
3626 }
3627
3628 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3629 fn vceil32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3630 let mut a = self.state[src].get_f32x4();
3631 for elem in a.iter_mut() {
3632 *elem = elem.wasm_ceil();
3633 }
3634 self.state[dst].set_f32x4(a);
3635
3636 ControlFlow::Continue(())
3637 }
3638
3639 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3640 fn vceil64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3641 let mut a = self.state[src].get_f64x2();
3642 for elem in a.iter_mut() {
3643 *elem = elem.wasm_ceil();
3644 }
3645 self.state[dst].set_f64x2(a);
3646
3647 ControlFlow::Continue(())
3648 }
3649
3650 fn fnearest32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3651 let a = self.state[src].get_f32();
3652 self.state[dst].set_f32(a.wasm_nearest());
3653 ControlFlow::Continue(())
3654 }
3655
3656 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3657 fn vnearest32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3658 let mut a = self.state[src].get_f32x4();
3659 for elem in a.iter_mut() {
3660 *elem = elem.wasm_nearest();
3661 }
3662 self.state[dst].set_f32x4(a);
3663 ControlFlow::Continue(())
3664 }
3665
3666 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3667 fn vnearest64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3668 let mut a = self.state[src].get_f64x2();
3669 for elem in a.iter_mut() {
3670 *elem = elem.wasm_nearest();
3671 }
3672 self.state[dst].set_f64x2(a);
3673 ControlFlow::Continue(())
3674 }
3675
3676 fn fsqrt32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3677 let a = self.state[src].get_f32();
3678 self.state[dst].set_f32(a.wasm_sqrt());
3679 ControlFlow::Continue(())
3680 }
3681
3682 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3683 fn vsqrt32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3684 let mut a = self.state[src].get_f32x4();
3685 for elem in a.iter_mut() {
3686 *elem = elem.wasm_sqrt();
3687 }
3688 self.state[dst].set_f32x4(a);
3689 ControlFlow::Continue(())
3690 }
3691
3692 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3693 fn vsqrt64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3694 let mut a = self.state[src].get_f64x2();
3695 for elem in a.iter_mut() {
3696 *elem = elem.wasm_sqrt();
3697 }
3698 self.state[dst].set_f64x2(a);
3699 ControlFlow::Continue(())
3700 }
3701
3702 fn fneg32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3703 let a = self.state[src].get_f32();
3704 self.state[dst].set_f32(-a);
3705 ControlFlow::Continue(())
3706 }
3707
3708 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3709 fn vnegf32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
3710 let mut a = self.state[src].get_f32x4();
3711 for elem in a.iter_mut() {
3712 *elem = -*elem;
3713 }
3714 self.state[dst].set_f32x4(a);
3715 ControlFlow::Continue(())
3716 }
3717
3718 fn fabs32(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3719 let a = self.state[src].get_f32();
3720 self.state[dst].set_f32(a.wasm_abs());
3721 ControlFlow::Continue(())
3722 }
3723
3724 fn fadd64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3725 let a = self.state[operands.src1].get_f64();
3726 let b = self.state[operands.src2].get_f64();
3727 self.state[operands.dst].set_f64(a + b);
3728 ControlFlow::Continue(())
3729 }
3730
3731 fn fsub64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3732 let a = self.state[operands.src1].get_f64();
3733 let b = self.state[operands.src2].get_f64();
3734 self.state[operands.dst].set_f64(a - b);
3735 ControlFlow::Continue(())
3736 }
3737
3738 fn fmul64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3739 let a = self.state[operands.src1].get_f64();
3740 let b = self.state[operands.src2].get_f64();
3741 self.state[operands.dst].set_f64(a * b);
3742 ControlFlow::Continue(())
3743 }
3744
3745 fn fdiv64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3746 let a = self.state[operands.src1].get_f64();
3747 let b = self.state[operands.src2].get_f64();
3748 self.state[operands.dst].set_f64(a / b);
3749 ControlFlow::Continue(())
3750 }
3751
3752 fn fmaximum64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3753 let a = self.state[operands.src1].get_f64();
3754 let b = self.state[operands.src2].get_f64();
3755 self.state[operands.dst].set_f64(a.wasm_maximum(b));
3756 ControlFlow::Continue(())
3757 }
3758
3759 fn fminimum64(&mut self, operands: BinaryOperands<FReg>) -> ControlFlow<Done> {
3760 let a = self.state[operands.src1].get_f64();
3761 let b = self.state[operands.src2].get_f64();
3762 self.state[operands.dst].set_f64(a.wasm_minimum(b));
3763 ControlFlow::Continue(())
3764 }
3765
3766 fn ftrunc64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3767 let a = self.state[src].get_f64();
3768 self.state[dst].set_f64(a.wasm_trunc());
3769 ControlFlow::Continue(())
3770 }
3771
3772 fn ffloor64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3773 let a = self.state[src].get_f64();
3774 self.state[dst].set_f64(a.wasm_floor());
3775 ControlFlow::Continue(())
3776 }
3777
3778 fn fceil64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3779 let a = self.state[src].get_f64();
3780 self.state[dst].set_f64(a.wasm_ceil());
3781 ControlFlow::Continue(())
3782 }
3783
3784 fn fnearest64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3785 let a = self.state[src].get_f64();
3786 self.state[dst].set_f64(a.wasm_nearest());
3787 ControlFlow::Continue(())
3788 }
3789
3790 fn fsqrt64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3791 let a = self.state[src].get_f64();
3792 self.state[dst].set_f64(a.wasm_sqrt());
3793 ControlFlow::Continue(())
3794 }
3795
3796 fn fneg64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3797 let a = self.state[src].get_f64();
3798 self.state[dst].set_f64(-a);
3799 ControlFlow::Continue(())
3800 }
3801
3802 fn fabs64(&mut self, dst: FReg, src: FReg) -> ControlFlow<Done> {
3803 let a = self.state[src].get_f64();
3804 self.state[dst].set_f64(a.wasm_abs());
3805 ControlFlow::Continue(())
3806 }
3807
3808 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3809 fn vaddi8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3810 let mut a = self.state[operands.src1].get_i8x16();
3811 let b = self.state[operands.src2].get_i8x16();
3812 for (a, b) in a.iter_mut().zip(b) {
3813 *a = a.wrapping_add(b);
3814 }
3815 self.state[operands.dst].set_i8x16(a);
3816 ControlFlow::Continue(())
3817 }
3818
3819 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3820 fn vaddi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3821 let mut a = self.state[operands.src1].get_i16x8();
3822 let b = self.state[operands.src2].get_i16x8();
3823 for (a, b) in a.iter_mut().zip(b) {
3824 *a = a.wrapping_add(b);
3825 }
3826 self.state[operands.dst].set_i16x8(a);
3827 ControlFlow::Continue(())
3828 }
3829
3830 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3831 fn vaddi32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3832 let mut a = self.state[operands.src1].get_i32x4();
3833 let b = self.state[operands.src2].get_i32x4();
3834 for (a, b) in a.iter_mut().zip(b) {
3835 *a = a.wrapping_add(b);
3836 }
3837 self.state[operands.dst].set_i32x4(a);
3838 ControlFlow::Continue(())
3839 }
3840
3841 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3842 fn vaddi64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3843 let mut a = self.state[operands.src1].get_i64x2();
3844 let b = self.state[operands.src2].get_i64x2();
3845 for (a, b) in a.iter_mut().zip(b) {
3846 *a = a.wrapping_add(b);
3847 }
3848 self.state[operands.dst].set_i64x2(a);
3849 ControlFlow::Continue(())
3850 }
3851
3852 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3853 fn vaddf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3854 let mut a = self.state[operands.src1].get_f32x4();
3855 let b = self.state[operands.src2].get_f32x4();
3856 for (a, b) in a.iter_mut().zip(b) {
3857 *a += b;
3858 }
3859 self.state[operands.dst].set_f32x4(a);
3860 ControlFlow::Continue(())
3861 }
3862
3863 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3864 fn vaddf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3865 let mut a = self.state[operands.src1].get_f64x2();
3866 let b = self.state[operands.src2].get_f64x2();
3867 for (a, b) in a.iter_mut().zip(b) {
3868 *a += b;
3869 }
3870 self.state[operands.dst].set_f64x2(a);
3871 ControlFlow::Continue(())
3872 }
3873
3874 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3875 fn vaddi8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3876 let mut a = self.state[operands.src1].get_i8x16();
3877 let b = self.state[operands.src2].get_i8x16();
3878 for (a, b) in a.iter_mut().zip(b) {
3879 *a = (*a).saturating_add(b);
3880 }
3881 self.state[operands.dst].set_i8x16(a);
3882 ControlFlow::Continue(())
3883 }
3884
3885 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3886 fn vaddu8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3887 let mut a = self.state[operands.src1].get_u8x16();
3888 let b = self.state[operands.src2].get_u8x16();
3889 for (a, b) in a.iter_mut().zip(b) {
3890 *a = (*a).saturating_add(b);
3891 }
3892 self.state[operands.dst].set_u8x16(a);
3893 ControlFlow::Continue(())
3894 }
3895
3896 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3897 fn vaddi16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3898 let mut a = self.state[operands.src1].get_i16x8();
3899 let b = self.state[operands.src2].get_i16x8();
3900 for (a, b) in a.iter_mut().zip(b) {
3901 *a = (*a).saturating_add(b);
3902 }
3903 self.state[operands.dst].set_i16x8(a);
3904 ControlFlow::Continue(())
3905 }
3906
3907 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3908 fn vaddu16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3909 let mut a = self.state[operands.src1].get_u16x8();
3910 let b = self.state[operands.src2].get_u16x8();
3911 for (a, b) in a.iter_mut().zip(b) {
3912 *a = (*a).saturating_add(b);
3913 }
3914 self.state[operands.dst].set_u16x8(a);
3915 ControlFlow::Continue(())
3916 }
3917
3918 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3919 fn vaddpairwisei16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3920 let a = self.state[operands.src1].get_i16x8();
3921 let b = self.state[operands.src2].get_i16x8();
3922 let mut result = [0i16; 8];
3923 let half = result.len() / 2;
3924 for i in 0..half {
3925 result[i] = a[2 * i].wrapping_add(a[2 * i + 1]);
3926 result[i + half] = b[2 * i].wrapping_add(b[2 * i + 1]);
3927 }
3928 self.state[operands.dst].set_i16x8(result);
3929 ControlFlow::Continue(())
3930 }
3931
3932 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3933 fn vaddpairwisei32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
3934 let a = self.state[operands.src1].get_i32x4();
3935 let b = self.state[operands.src2].get_i32x4();
3936 let mut result = [0i32; 4];
3937 result[0] = a[0].wrapping_add(a[1]);
3938 result[1] = a[2].wrapping_add(a[3]);
3939 result[2] = b[0].wrapping_add(b[1]);
3940 result[3] = b[2].wrapping_add(b[3]);
3941 self.state[operands.dst].set_i32x4(result);
3942 ControlFlow::Continue(())
3943 }
3944
3945 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3946 fn vshli8x16(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3947 let a = self.state[operands.src1].get_i8x16();
3948 let b = self.state[operands.src2].get_u32();
3949 self.state[operands.dst].set_i8x16(a.map(|a| a.wrapping_shl(b)));
3950 ControlFlow::Continue(())
3951 }
3952
3953 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3954 fn vshli16x8(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3955 let a = self.state[operands.src1].get_i16x8();
3956 let b = self.state[operands.src2].get_u32();
3957 self.state[operands.dst].set_i16x8(a.map(|a| a.wrapping_shl(b)));
3958 ControlFlow::Continue(())
3959 }
3960
3961 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3962 fn vshli32x4(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3963 let a = self.state[operands.src1].get_i32x4();
3964 let b = self.state[operands.src2].get_u32();
3965 self.state[operands.dst].set_i32x4(a.map(|a| a.wrapping_shl(b)));
3966 ControlFlow::Continue(())
3967 }
3968
3969 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3970 fn vshli64x2(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3971 let a = self.state[operands.src1].get_i64x2();
3972 let b = self.state[operands.src2].get_u32();
3973 self.state[operands.dst].set_i64x2(a.map(|a| a.wrapping_shl(b)));
3974 ControlFlow::Continue(())
3975 }
3976
3977 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3978 fn vshri8x16_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3979 let a = self.state[operands.src1].get_i8x16();
3980 let b = self.state[operands.src2].get_u32();
3981 self.state[operands.dst].set_i8x16(a.map(|a| a.wrapping_shr(b)));
3982 ControlFlow::Continue(())
3983 }
3984
3985 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3986 fn vshri16x8_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3987 let a = self.state[operands.src1].get_i16x8();
3988 let b = self.state[operands.src2].get_u32();
3989 self.state[operands.dst].set_i16x8(a.map(|a| a.wrapping_shr(b)));
3990 ControlFlow::Continue(())
3991 }
3992
3993 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
3994 fn vshri32x4_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
3995 let a = self.state[operands.src1].get_i32x4();
3996 let b = self.state[operands.src2].get_u32();
3997 self.state[operands.dst].set_i32x4(a.map(|a| a.wrapping_shr(b)));
3998 ControlFlow::Continue(())
3999 }
4000
4001 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4002 fn vshri64x2_s(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
4003 let a = self.state[operands.src1].get_i64x2();
4004 let b = self.state[operands.src2].get_u32();
4005 self.state[operands.dst].set_i64x2(a.map(|a| a.wrapping_shr(b)));
4006 ControlFlow::Continue(())
4007 }
4008
4009 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4010 fn vshri8x16_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
4011 let a = self.state[operands.src1].get_u8x16();
4012 let b = self.state[operands.src2].get_u32();
4013 self.state[operands.dst].set_u8x16(a.map(|a| a.wrapping_shr(b)));
4014 ControlFlow::Continue(())
4015 }
4016
4017 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4018 fn vshri16x8_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
4019 let a = self.state[operands.src1].get_u16x8();
4020 let b = self.state[operands.src2].get_u32();
4021 self.state[operands.dst].set_u16x8(a.map(|a| a.wrapping_shr(b)));
4022 ControlFlow::Continue(())
4023 }
4024
4025 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4026 fn vshri32x4_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
4027 let a = self.state[operands.src1].get_u32x4();
4028 let b = self.state[operands.src2].get_u32();
4029 self.state[operands.dst].set_u32x4(a.map(|a| a.wrapping_shr(b)));
4030 ControlFlow::Continue(())
4031 }
4032
4033 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4034 fn vshri64x2_u(&mut self, operands: BinaryOperands<VReg, VReg, XReg>) -> ControlFlow<Done> {
4035 let a = self.state[operands.src1].get_u64x2();
4036 let b = self.state[operands.src2].get_u32();
4037 self.state[operands.dst].set_u64x2(a.map(|a| a.wrapping_shr(b)));
4038 ControlFlow::Continue(())
4039 }
4040
4041 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4042 fn vconst128(&mut self, dst: VReg, val: u128) -> ControlFlow<Done> {
4043 self.state[dst].set_u128(val);
4044 ControlFlow::Continue(())
4045 }
4046
4047 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4048 fn vsplatx8(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
4049 let val = self.state[src].get_u32() as u8;
4050 self.state[dst].set_u8x16([val; 16]);
4051 ControlFlow::Continue(())
4052 }
4053
4054 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4055 fn vsplatx16(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
4056 let val = self.state[src].get_u32() as u16;
4057 self.state[dst].set_u16x8([val; 8]);
4058 ControlFlow::Continue(())
4059 }
4060
4061 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4062 fn vsplatx32(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
4063 let val = self.state[src].get_u32();
4064 self.state[dst].set_u32x4([val; 4]);
4065 ControlFlow::Continue(())
4066 }
4067
4068 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4069 fn vsplatx64(&mut self, dst: VReg, src: XReg) -> ControlFlow<Done> {
4070 let val = self.state[src].get_u64();
4071 self.state[dst].set_u64x2([val; 2]);
4072 ControlFlow::Continue(())
4073 }
4074
4075 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4076 fn vsplatf32(&mut self, dst: VReg, src: FReg) -> ControlFlow<Done> {
4077 let val = self.state[src].get_f32();
4078 self.state[dst].set_f32x4([val; 4]);
4079 ControlFlow::Continue(())
4080 }
4081
4082 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4083 fn vsplatf64(&mut self, dst: VReg, src: FReg) -> ControlFlow<Done> {
4084 let val = self.state[src].get_f64();
4085 self.state[dst].set_f64x2([val; 2]);
4086 ControlFlow::Continue(())
4087 }
4088
4089 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4090 fn vload8x8_s_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4091 let val = unsafe { self.load_ne::<[i8; 8], crate::VLoad8x8SZ>(addr)? };
4092 self.state[dst].set_i16x8(val.map(|i| i.into()));
4093 ControlFlow::Continue(())
4094 }
4095
4096 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4097 fn vload8x8_u_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4098 let val = unsafe { self.load_ne::<[u8; 8], crate::VLoad8x8UZ>(addr)? };
4099 self.state[dst].set_u16x8(val.map(|i| i.into()));
4100 ControlFlow::Continue(())
4101 }
4102
4103 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4104 fn vload16x4le_s_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4105 let val = unsafe { self.load_ne::<[i16; 4], crate::VLoad16x4LeSZ>(addr)? };
4106 self.state[dst].set_i32x4(val.map(|i| i16::from_le(i).into()));
4107 ControlFlow::Continue(())
4108 }
4109
4110 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4111 fn vload16x4le_u_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4112 let val = unsafe { self.load_ne::<[u16; 4], crate::VLoad16x4LeUZ>(addr)? };
4113 self.state[dst].set_u32x4(val.map(|i| u16::from_le(i).into()));
4114 ControlFlow::Continue(())
4115 }
4116
4117 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4118 fn vload32x2le_s_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4119 let val = unsafe { self.load_ne::<[i32; 2], crate::VLoad32x2LeSZ>(addr)? };
4120 self.state[dst].set_i64x2(val.map(|i| i32::from_le(i).into()));
4121 ControlFlow::Continue(())
4122 }
4123
4124 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4125 fn vload32x2le_u_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
4126 let val = unsafe { self.load_ne::<[u32; 2], crate::VLoad32x2LeUZ>(addr)? };
4127 self.state[dst].set_u64x2(val.map(|i| u32::from_le(i).into()));
4128 ControlFlow::Continue(())
4129 }
4130
4131 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4132 fn vband128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4133 let a = self.state[operands.src1].get_u128();
4134 let b = self.state[operands.src2].get_u128();
4135 self.state[operands.dst].set_u128(a & b);
4136 ControlFlow::Continue(())
4137 }
4138
4139 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4140 fn vbor128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4141 let a = self.state[operands.src1].get_u128();
4142 let b = self.state[operands.src2].get_u128();
4143 self.state[operands.dst].set_u128(a | b);
4144 ControlFlow::Continue(())
4145 }
4146
4147 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4148 fn vbxor128(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4149 let a = self.state[operands.src1].get_u128();
4150 let b = self.state[operands.src2].get_u128();
4151 self.state[operands.dst].set_u128(a ^ b);
4152 ControlFlow::Continue(())
4153 }
4154
4155 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4156 fn vbnot128(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4157 let a = self.state[src].get_u128();
4158 self.state[dst].set_u128(!a);
4159 ControlFlow::Continue(())
4160 }
4161
4162 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4163 fn vbitselect128(&mut self, dst: VReg, c: VReg, x: VReg, y: VReg) -> ControlFlow<Done> {
4164 let c = self.state[c].get_u128();
4165 let x = self.state[x].get_u128();
4166 let y = self.state[y].get_u128();
4167 self.state[dst].set_u128((c & x) | (!c & y));
4168 ControlFlow::Continue(())
4169 }
4170
4171 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4172 fn vbitmask8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4173 let a = self.state[src].get_u8x16();
4174 let mut result = 0;
4175 for item in a.iter().rev() {
4176 result <<= 1;
4177 result |= (*item >> 7) as u32;
4178 }
4179 self.state[dst].set_u32(result);
4180 ControlFlow::Continue(())
4181 }
4182
4183 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4184 fn vbitmask16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4185 let a = self.state[src].get_u16x8();
4186 let mut result = 0;
4187 for item in a.iter().rev() {
4188 result <<= 1;
4189 result |= (*item >> 15) as u32;
4190 }
4191 self.state[dst].set_u32(result);
4192 ControlFlow::Continue(())
4193 }
4194
4195 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4196 fn vbitmask32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4197 let a = self.state[src].get_u32x4();
4198 let mut result = 0;
4199 for item in a.iter().rev() {
4200 result <<= 1;
4201 result |= *item >> 31;
4202 }
4203 self.state[dst].set_u32(result);
4204 ControlFlow::Continue(())
4205 }
4206
4207 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4208 fn vbitmask64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4209 let a = self.state[src].get_u64x2();
4210 let mut result = 0;
4211 for item in a.iter().rev() {
4212 result <<= 1;
4213 result |= (*item >> 63) as u32;
4214 }
4215 self.state[dst].set_u32(result);
4216 ControlFlow::Continue(())
4217 }
4218
4219 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4220 fn valltrue8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4221 let a = self.state[src].get_u8x16();
4222 let result = a.iter().all(|a| *a != 0);
4223 self.state[dst].set_u32(u32::from(result));
4224 ControlFlow::Continue(())
4225 }
4226
4227 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4228 fn valltrue16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4229 let a = self.state[src].get_u16x8();
4230 let result = a.iter().all(|a| *a != 0);
4231 self.state[dst].set_u32(u32::from(result));
4232 ControlFlow::Continue(())
4233 }
4234
4235 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4236 fn valltrue32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4237 let a = self.state[src].get_u32x4();
4238 let result = a.iter().all(|a| *a != 0);
4239 self.state[dst].set_u32(u32::from(result));
4240 ControlFlow::Continue(())
4241 }
4242
4243 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4244 fn valltrue64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4245 let a = self.state[src].get_u64x2();
4246 let result = a.iter().all(|a| *a != 0);
4247 self.state[dst].set_u32(u32::from(result));
4248 ControlFlow::Continue(())
4249 }
4250
4251 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4252 fn vanytrue8x16(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4253 let a = self.state[src].get_u8x16();
4254 let result = a.iter().any(|a| *a != 0);
4255 self.state[dst].set_u32(u32::from(result));
4256 ControlFlow::Continue(())
4257 }
4258
4259 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4260 fn vanytrue16x8(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4261 let a = self.state[src].get_u16x8();
4262 let result = a.iter().any(|a| *a != 0);
4263 self.state[dst].set_u32(u32::from(result));
4264 ControlFlow::Continue(())
4265 }
4266
4267 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4268 fn vanytrue32x4(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4269 let a = self.state[src].get_u32x4();
4270 let result = a.iter().any(|a| *a != 0);
4271 self.state[dst].set_u32(u32::from(result));
4272 ControlFlow::Continue(())
4273 }
4274
4275 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4276 fn vanytrue64x2(&mut self, dst: XReg, src: VReg) -> ControlFlow<Done> {
4277 let a = self.state[src].get_u64x2();
4278 let result = a.iter().any(|a| *a != 0);
4279 self.state[dst].set_u32(u32::from(result));
4280 ControlFlow::Continue(())
4281 }
4282
4283 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4284 fn vf32x4_from_i32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4285 let a = self.state[src].get_i32x4();
4286 self.state[dst].set_f32x4(a.map(|i| i as f32));
4287 ControlFlow::Continue(())
4288 }
4289
4290 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4291 fn vf32x4_from_i32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4292 let a = self.state[src].get_u32x4();
4293 self.state[dst].set_f32x4(a.map(|i| i as f32));
4294 ControlFlow::Continue(())
4295 }
4296
4297 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4298 fn vf64x2_from_i64x2_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4299 let a = self.state[src].get_i64x2();
4300 self.state[dst].set_f64x2(a.map(|i| i as f64));
4301 ControlFlow::Continue(())
4302 }
4303
4304 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4305 fn vf64x2_from_i64x2_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4306 let a = self.state[src].get_u64x2();
4307 self.state[dst].set_f64x2(a.map(|i| i as f64));
4308 ControlFlow::Continue(())
4309 }
4310
4311 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4312 fn vi32x4_from_f32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4313 let a = self.state[src].get_f32x4();
4314 self.state[dst].set_i32x4(a.map(|f| f as i32));
4315 ControlFlow::Continue(())
4316 }
4317
4318 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4319 fn vi32x4_from_f32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4320 let a = self.state[src].get_f32x4();
4321 self.state[dst].set_u32x4(a.map(|f| f as u32));
4322 ControlFlow::Continue(())
4323 }
4324
4325 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4326 fn vi64x2_from_f64x2_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4327 let a = self.state[src].get_f64x2();
4328 self.state[dst].set_i64x2(a.map(|f| f as i64));
4329 ControlFlow::Continue(())
4330 }
4331
4332 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4333 fn vi64x2_from_f64x2_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4334 let a = self.state[src].get_f64x2();
4335 self.state[dst].set_u64x2(a.map(|f| f as u64));
4336 ControlFlow::Continue(())
4337 }
4338
4339 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4340 fn vwidenlow8x16_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4341 let a = *self.state[src].get_i8x16().first_chunk().unwrap();
4342 self.state[dst].set_i16x8(a.map(|i| i.into()));
4343 ControlFlow::Continue(())
4344 }
4345
4346 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4347 fn vwidenlow8x16_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4348 let a = *self.state[src].get_u8x16().first_chunk().unwrap();
4349 self.state[dst].set_u16x8(a.map(|i| i.into()));
4350 ControlFlow::Continue(())
4351 }
4352
4353 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4354 fn vwidenlow16x8_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4355 let a = *self.state[src].get_i16x8().first_chunk().unwrap();
4356 self.state[dst].set_i32x4(a.map(|i| i.into()));
4357 ControlFlow::Continue(())
4358 }
4359
4360 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4361 fn vwidenlow16x8_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4362 let a = *self.state[src].get_u16x8().first_chunk().unwrap();
4363 self.state[dst].set_u32x4(a.map(|i| i.into()));
4364 ControlFlow::Continue(())
4365 }
4366
4367 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4368 fn vwidenlow32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4369 let a = *self.state[src].get_i32x4().first_chunk().unwrap();
4370 self.state[dst].set_i64x2(a.map(|i| i.into()));
4371 ControlFlow::Continue(())
4372 }
4373
4374 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4375 fn vwidenlow32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4376 let a = *self.state[src].get_u32x4().first_chunk().unwrap();
4377 self.state[dst].set_u64x2(a.map(|i| i.into()));
4378 ControlFlow::Continue(())
4379 }
4380
4381 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4382 fn vwidenhigh8x16_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4383 let a = *self.state[src].get_i8x16().last_chunk().unwrap();
4384 self.state[dst].set_i16x8(a.map(|i| i.into()));
4385 ControlFlow::Continue(())
4386 }
4387
4388 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4389 fn vwidenhigh8x16_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4390 let a = *self.state[src].get_u8x16().last_chunk().unwrap();
4391 self.state[dst].set_u16x8(a.map(|i| i.into()));
4392 ControlFlow::Continue(())
4393 }
4394
4395 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4396 fn vwidenhigh16x8_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4397 let a = *self.state[src].get_i16x8().last_chunk().unwrap();
4398 self.state[dst].set_i32x4(a.map(|i| i.into()));
4399 ControlFlow::Continue(())
4400 }
4401
4402 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4403 fn vwidenhigh16x8_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4404 let a = *self.state[src].get_u16x8().last_chunk().unwrap();
4405 self.state[dst].set_u32x4(a.map(|i| i.into()));
4406 ControlFlow::Continue(())
4407 }
4408
4409 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4410 fn vwidenhigh32x4_s(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4411 let a = *self.state[src].get_i32x4().last_chunk().unwrap();
4412 self.state[dst].set_i64x2(a.map(|i| i.into()));
4413 ControlFlow::Continue(())
4414 }
4415
4416 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4417 fn vwidenhigh32x4_u(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4418 let a = *self.state[src].get_u32x4().last_chunk().unwrap();
4419 self.state[dst].set_u64x2(a.map(|i| i.into()));
4420 ControlFlow::Continue(())
4421 }
4422
4423 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4424 fn vnarrow16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4425 let a = self.state[operands.src1].get_i16x8();
4426 let b = self.state[operands.src2].get_i16x8();
4427 let mut result = [0; 16];
4428 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4429 *d = (*i)
4430 .try_into()
4431 .unwrap_or(if *i < 0 { i8::MIN } else { i8::MAX });
4432 }
4433 self.state[operands.dst].set_i8x16(result);
4434 ControlFlow::Continue(())
4435 }
4436
4437 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4438 fn vnarrow16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4439 let a = self.state[operands.src1].get_i16x8();
4440 let b = self.state[operands.src2].get_i16x8();
4441 let mut result = [0; 16];
4442 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4443 *d = (*i)
4444 .try_into()
4445 .unwrap_or(if *i < 0 { u8::MIN } else { u8::MAX });
4446 }
4447 self.state[operands.dst].set_u8x16(result);
4448 ControlFlow::Continue(())
4449 }
4450
4451 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4452 fn vnarrow32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4453 let a = self.state[operands.src1].get_i32x4();
4454 let b = self.state[operands.src2].get_i32x4();
4455 let mut result = [0; 8];
4456 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4457 *d = (*i)
4458 .try_into()
4459 .unwrap_or(if *i < 0 { i16::MIN } else { i16::MAX });
4460 }
4461 self.state[operands.dst].set_i16x8(result);
4462 ControlFlow::Continue(())
4463 }
4464
4465 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4466 fn vnarrow32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4467 let a = self.state[operands.src1].get_i32x4();
4468 let b = self.state[operands.src2].get_i32x4();
4469 let mut result = [0; 8];
4470 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4471 *d = (*i)
4472 .try_into()
4473 .unwrap_or(if *i < 0 { u16::MIN } else { u16::MAX });
4474 }
4475 self.state[operands.dst].set_u16x8(result);
4476 ControlFlow::Continue(())
4477 }
4478
4479 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4480 fn vnarrow64x2_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4481 let a = self.state[operands.src1].get_i64x2();
4482 let b = self.state[operands.src2].get_i64x2();
4483 let mut result = [0; 4];
4484 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4485 *d = (*i)
4486 .try_into()
4487 .unwrap_or(if *i < 0 { i32::MIN } else { i32::MAX });
4488 }
4489 self.state[operands.dst].set_i32x4(result);
4490 ControlFlow::Continue(())
4491 }
4492
4493 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4494 fn vnarrow64x2_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4495 let a = self.state[operands.src1].get_i64x2();
4496 let b = self.state[operands.src2].get_i64x2();
4497 let mut result = [0; 4];
4498 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4499 *d = (*i)
4500 .try_into()
4501 .unwrap_or(if *i < 0 { u32::MIN } else { u32::MAX });
4502 }
4503 self.state[operands.dst].set_u32x4(result);
4504 ControlFlow::Continue(())
4505 }
4506
4507 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4508 fn vunarrow64x2_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4509 let a = self.state[operands.src1].get_u64x2();
4510 let b = self.state[operands.src2].get_u64x2();
4511 let mut result = [0; 4];
4512 for (i, d) in a.iter().chain(&b).zip(&mut result) {
4513 *d = (*i).try_into().unwrap_or(u32::MAX);
4514 }
4515 self.state[operands.dst].set_u32x4(result);
4516 ControlFlow::Continue(())
4517 }
4518
4519 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4520 fn vfpromotelow(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4521 let a = self.state[src].get_f32x4();
4522 self.state[dst].set_f64x2([a[0].into(), a[1].into()]);
4523 ControlFlow::Continue(())
4524 }
4525
4526 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4527 fn vfdemote(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4528 let a = self.state[src].get_f64x2();
4529 self.state[dst].set_f32x4([a[0] as f32, a[1] as f32, 0.0, 0.0]);
4530 ControlFlow::Continue(())
4531 }
4532
4533 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4534 fn vsubi8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4535 let mut a = self.state[operands.src1].get_i8x16();
4536 let b = self.state[operands.src2].get_i8x16();
4537 for (a, b) in a.iter_mut().zip(b) {
4538 *a = a.wrapping_sub(b);
4539 }
4540 self.state[operands.dst].set_i8x16(a);
4541 ControlFlow::Continue(())
4542 }
4543
4544 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4545 fn vsubi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4546 let mut a = self.state[operands.src1].get_i16x8();
4547 let b = self.state[operands.src2].get_i16x8();
4548 for (a, b) in a.iter_mut().zip(b) {
4549 *a = a.wrapping_sub(b);
4550 }
4551 self.state[operands.dst].set_i16x8(a);
4552 ControlFlow::Continue(())
4553 }
4554
4555 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4556 fn vsubi32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4557 let mut a = self.state[operands.src1].get_i32x4();
4558 let b = self.state[operands.src2].get_i32x4();
4559 for (a, b) in a.iter_mut().zip(b) {
4560 *a = a.wrapping_sub(b);
4561 }
4562 self.state[operands.dst].set_i32x4(a);
4563 ControlFlow::Continue(())
4564 }
4565
4566 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4567 fn vsubi64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4568 let mut a = self.state[operands.src1].get_i64x2();
4569 let b = self.state[operands.src2].get_i64x2();
4570 for (a, b) in a.iter_mut().zip(b) {
4571 *a = a.wrapping_sub(b);
4572 }
4573 self.state[operands.dst].set_i64x2(a);
4574 ControlFlow::Continue(())
4575 }
4576
4577 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4578 fn vsubi8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4579 let mut a = self.state[operands.src1].get_i8x16();
4580 let b = self.state[operands.src2].get_i8x16();
4581 for (a, b) in a.iter_mut().zip(b) {
4582 *a = a.saturating_sub(b);
4583 }
4584 self.state[operands.dst].set_i8x16(a);
4585 ControlFlow::Continue(())
4586 }
4587
4588 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4589 fn vsubu8x16_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4590 let mut a = self.state[operands.src1].get_u8x16();
4591 let b = self.state[operands.src2].get_u8x16();
4592 for (a, b) in a.iter_mut().zip(b) {
4593 *a = a.saturating_sub(b);
4594 }
4595 self.state[operands.dst].set_u8x16(a);
4596 ControlFlow::Continue(())
4597 }
4598
4599 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4600 fn vsubi16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4601 let mut a = self.state[operands.src1].get_i16x8();
4602 let b = self.state[operands.src2].get_i16x8();
4603 for (a, b) in a.iter_mut().zip(b) {
4604 *a = a.saturating_sub(b);
4605 }
4606 self.state[operands.dst].set_i16x8(a);
4607 ControlFlow::Continue(())
4608 }
4609
4610 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4611 fn vsubu16x8_sat(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4612 let mut a = self.state[operands.src1].get_u16x8();
4613 let b = self.state[operands.src2].get_u16x8();
4614 for (a, b) in a.iter_mut().zip(b) {
4615 *a = a.saturating_sub(b);
4616 }
4617 self.state[operands.dst].set_u16x8(a);
4618 ControlFlow::Continue(())
4619 }
4620
4621 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4622 fn vsubf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4623 let mut a = self.state[operands.src1].get_f64x2();
4624 let b = self.state[operands.src2].get_f64x2();
4625 for (a, b) in a.iter_mut().zip(b) {
4626 *a = *a - b;
4627 }
4628 self.state[operands.dst].set_f64x2(a);
4629 ControlFlow::Continue(())
4630 }
4631
4632 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4633 fn vmuli8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4634 let mut a = self.state[operands.src1].get_i8x16();
4635 let b = self.state[operands.src2].get_i8x16();
4636 for (a, b) in a.iter_mut().zip(b) {
4637 *a = a.wrapping_mul(b);
4638 }
4639 self.state[operands.dst].set_i8x16(a);
4640 ControlFlow::Continue(())
4641 }
4642
4643 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4644 fn vmuli16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4645 let mut a = self.state[operands.src1].get_i16x8();
4646 let b = self.state[operands.src2].get_i16x8();
4647 for (a, b) in a.iter_mut().zip(b) {
4648 *a = a.wrapping_mul(b);
4649 }
4650 self.state[operands.dst].set_i16x8(a);
4651 ControlFlow::Continue(())
4652 }
4653
4654 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4655 fn vmuli32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4656 let mut a = self.state[operands.src1].get_i32x4();
4657 let b = self.state[operands.src2].get_i32x4();
4658 for (a, b) in a.iter_mut().zip(b) {
4659 *a = a.wrapping_mul(b);
4660 }
4661 self.state[operands.dst].set_i32x4(a);
4662 ControlFlow::Continue(())
4663 }
4664
4665 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4666 fn vmuli64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4667 let mut a = self.state[operands.src1].get_i64x2();
4668 let b = self.state[operands.src2].get_i64x2();
4669 for (a, b) in a.iter_mut().zip(b) {
4670 *a = a.wrapping_mul(b);
4671 }
4672 self.state[operands.dst].set_i64x2(a);
4673 ControlFlow::Continue(())
4674 }
4675
4676 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4677 fn vmulf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4678 let mut a = self.state[operands.src1].get_f64x2();
4679 let b = self.state[operands.src2].get_f64x2();
4680 for (a, b) in a.iter_mut().zip(b) {
4681 *a = *a * b;
4682 }
4683 self.state[operands.dst].set_f64x2(a);
4684 ControlFlow::Continue(())
4685 }
4686
4687 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4688 fn vqmulrsi16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4689 let mut a = self.state[operands.src1].get_i16x8();
4690 let b = self.state[operands.src2].get_i16x8();
4691 const MIN: i32 = i16::MIN as i32;
4692 const MAX: i32 = i16::MAX as i32;
4693 for (a, b) in a.iter_mut().zip(b) {
4694 let r = (i32::from(*a) * i32::from(b) + (1 << 14)) >> 15;
4695 *a = r.clamp(MIN, MAX) as i16;
4696 }
4697 self.state[operands.dst].set_i16x8(a);
4698 ControlFlow::Continue(())
4699 }
4700
4701 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4702 fn vpopcnt8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
4703 let a = self.state[src].get_u8x16();
4704 self.state[dst].set_u8x16(a.map(|i| i.count_ones() as u8));
4705 ControlFlow::Continue(())
4706 }
4707
4708 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4709 fn xextractv8x16(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4710 let a = unsafe { *self.state[src].get_u8x16().get_unchecked(usize::from(lane)) };
4711 self.state[dst].set_u32(u32::from(a));
4712 ControlFlow::Continue(())
4713 }
4714
4715 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4716 fn xextractv16x8(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4717 let a = unsafe { *self.state[src].get_u16x8().get_unchecked(usize::from(lane)) };
4718 self.state[dst].set_u32(u32::from(a));
4719 ControlFlow::Continue(())
4720 }
4721
4722 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4723 fn xextractv32x4(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4724 let a = unsafe { *self.state[src].get_u32x4().get_unchecked(usize::from(lane)) };
4725 self.state[dst].set_u32(a);
4726 ControlFlow::Continue(())
4727 }
4728
4729 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4730 fn xextractv64x2(&mut self, dst: XReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4731 let a = unsafe { *self.state[src].get_u64x2().get_unchecked(usize::from(lane)) };
4732 self.state[dst].set_u64(a);
4733 ControlFlow::Continue(())
4734 }
4735
4736 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4737 fn fextractv32x4(&mut self, dst: FReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4738 let a = unsafe { *self.state[src].get_f32x4().get_unchecked(usize::from(lane)) };
4739 self.state[dst].set_f32(a);
4740 ControlFlow::Continue(())
4741 }
4742
4743 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4744 fn fextractv64x2(&mut self, dst: FReg, src: VReg, lane: u8) -> ControlFlow<Done> {
4745 let a = unsafe { *self.state[src].get_f64x2().get_unchecked(usize::from(lane)) };
4746 self.state[dst].set_f64(a);
4747 ControlFlow::Continue(())
4748 }
4749
4750 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4751 fn vinsertx8(
4752 &mut self,
4753 operands: BinaryOperands<VReg, VReg, XReg>,
4754 lane: u8,
4755 ) -> ControlFlow<Done> {
4756 let mut a = self.state[operands.src1].get_u8x16();
4757 let b = self.state[operands.src2].get_u32() as u8;
4758 unsafe {
4759 *a.get_unchecked_mut(usize::from(lane)) = b;
4760 }
4761 self.state[operands.dst].set_u8x16(a);
4762 ControlFlow::Continue(())
4763 }
4764
4765 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4766 fn vinsertx16(
4767 &mut self,
4768 operands: BinaryOperands<VReg, VReg, XReg>,
4769 lane: u8,
4770 ) -> ControlFlow<Done> {
4771 let mut a = self.state[operands.src1].get_u16x8();
4772 let b = self.state[operands.src2].get_u32() as u16;
4773 unsafe {
4774 *a.get_unchecked_mut(usize::from(lane)) = b;
4775 }
4776 self.state[operands.dst].set_u16x8(a);
4777 ControlFlow::Continue(())
4778 }
4779
4780 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4781 fn vinsertx32(
4782 &mut self,
4783 operands: BinaryOperands<VReg, VReg, XReg>,
4784 lane: u8,
4785 ) -> ControlFlow<Done> {
4786 let mut a = self.state[operands.src1].get_u32x4();
4787 let b = self.state[operands.src2].get_u32();
4788 unsafe {
4789 *a.get_unchecked_mut(usize::from(lane)) = b;
4790 }
4791 self.state[operands.dst].set_u32x4(a);
4792 ControlFlow::Continue(())
4793 }
4794
4795 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4796 fn vinsertx64(
4797 &mut self,
4798 operands: BinaryOperands<VReg, VReg, XReg>,
4799 lane: u8,
4800 ) -> ControlFlow<Done> {
4801 let mut a = self.state[operands.src1].get_u64x2();
4802 let b = self.state[operands.src2].get_u64();
4803 unsafe {
4804 *a.get_unchecked_mut(usize::from(lane)) = b;
4805 }
4806 self.state[operands.dst].set_u64x2(a);
4807 ControlFlow::Continue(())
4808 }
4809
4810 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4811 fn vinsertf32(
4812 &mut self,
4813 operands: BinaryOperands<VReg, VReg, FReg>,
4814 lane: u8,
4815 ) -> ControlFlow<Done> {
4816 let mut a = self.state[operands.src1].get_f32x4();
4817 let b = self.state[operands.src2].get_f32();
4818 unsafe {
4819 *a.get_unchecked_mut(usize::from(lane)) = b;
4820 }
4821 self.state[operands.dst].set_f32x4(a);
4822 ControlFlow::Continue(())
4823 }
4824
4825 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4826 fn vinsertf64(
4827 &mut self,
4828 operands: BinaryOperands<VReg, VReg, FReg>,
4829 lane: u8,
4830 ) -> ControlFlow<Done> {
4831 let mut a = self.state[operands.src1].get_f64x2();
4832 let b = self.state[operands.src2].get_f64();
4833 unsafe {
4834 *a.get_unchecked_mut(usize::from(lane)) = b;
4835 }
4836 self.state[operands.dst].set_f64x2(a);
4837 ControlFlow::Continue(())
4838 }
4839
4840 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4841 fn veq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4842 let a = self.state[operands.src1].get_u8x16();
4843 let b = self.state[operands.src2].get_u8x16();
4844 let mut c = [0; 16];
4845 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4846 *c = if a == b { u8::MAX } else { 0 };
4847 }
4848 self.state[operands.dst].set_u8x16(c);
4849 ControlFlow::Continue(())
4850 }
4851
4852 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4853 fn vneq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4854 let a = self.state[operands.src1].get_u8x16();
4855 let b = self.state[operands.src2].get_u8x16();
4856 let mut c = [0; 16];
4857 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4858 *c = if a != b { u8::MAX } else { 0 };
4859 }
4860 self.state[operands.dst].set_u8x16(c);
4861 ControlFlow::Continue(())
4862 }
4863
4864 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4865 fn vslt8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4866 let a = self.state[operands.src1].get_i8x16();
4867 let b = self.state[operands.src2].get_i8x16();
4868 let mut c = [0; 16];
4869 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4870 *c = if a < b { u8::MAX } else { 0 };
4871 }
4872 self.state[operands.dst].set_u8x16(c);
4873 ControlFlow::Continue(())
4874 }
4875
4876 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4877 fn vslteq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4878 let a = self.state[operands.src1].get_i8x16();
4879 let b = self.state[operands.src2].get_i8x16();
4880 let mut c = [0; 16];
4881 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4882 *c = if a <= b { u8::MAX } else { 0 };
4883 }
4884 self.state[operands.dst].set_u8x16(c);
4885 ControlFlow::Continue(())
4886 }
4887
4888 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4889 fn vult8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4890 let a = self.state[operands.src1].get_u8x16();
4891 let b = self.state[operands.src2].get_u8x16();
4892 let mut c = [0; 16];
4893 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4894 *c = if a < b { u8::MAX } else { 0 };
4895 }
4896 self.state[operands.dst].set_u8x16(c);
4897 ControlFlow::Continue(())
4898 }
4899
4900 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4901 fn vulteq8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4902 let a = self.state[operands.src1].get_u8x16();
4903 let b = self.state[operands.src2].get_u8x16();
4904 let mut c = [0; 16];
4905 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4906 *c = if a <= b { u8::MAX } else { 0 };
4907 }
4908 self.state[operands.dst].set_u8x16(c);
4909 ControlFlow::Continue(())
4910 }
4911
4912 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4913 fn veq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4914 let a = self.state[operands.src1].get_u16x8();
4915 let b = self.state[operands.src2].get_u16x8();
4916 let mut c = [0; 8];
4917 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4918 *c = if a == b { u16::MAX } else { 0 };
4919 }
4920 self.state[operands.dst].set_u16x8(c);
4921 ControlFlow::Continue(())
4922 }
4923
4924 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4925 fn vneq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4926 let a = self.state[operands.src1].get_u16x8();
4927 let b = self.state[operands.src2].get_u16x8();
4928 let mut c = [0; 8];
4929 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4930 *c = if a != b { u16::MAX } else { 0 };
4931 }
4932 self.state[operands.dst].set_u16x8(c);
4933 ControlFlow::Continue(())
4934 }
4935
4936 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4937 fn vslt16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4938 let a = self.state[operands.src1].get_i16x8();
4939 let b = self.state[operands.src2].get_i16x8();
4940 let mut c = [0; 8];
4941 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4942 *c = if a < b { u16::MAX } else { 0 };
4943 }
4944 self.state[operands.dst].set_u16x8(c);
4945 ControlFlow::Continue(())
4946 }
4947
4948 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4949 fn vslteq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4950 let a = self.state[operands.src1].get_i16x8();
4951 let b = self.state[operands.src2].get_i16x8();
4952 let mut c = [0; 8];
4953 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4954 *c = if a <= b { u16::MAX } else { 0 };
4955 }
4956 self.state[operands.dst].set_u16x8(c);
4957 ControlFlow::Continue(())
4958 }
4959
4960 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4961 fn vult16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4962 let a = self.state[operands.src1].get_u16x8();
4963 let b = self.state[operands.src2].get_u16x8();
4964 let mut c = [0; 8];
4965 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4966 *c = if a < b { u16::MAX } else { 0 };
4967 }
4968 self.state[operands.dst].set_u16x8(c);
4969 ControlFlow::Continue(())
4970 }
4971
4972 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4973 fn vulteq16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4974 let a = self.state[operands.src1].get_u16x8();
4975 let b = self.state[operands.src2].get_u16x8();
4976 let mut c = [0; 8];
4977 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4978 *c = if a <= b { u16::MAX } else { 0 };
4979 }
4980 self.state[operands.dst].set_u16x8(c);
4981 ControlFlow::Continue(())
4982 }
4983
4984 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4985 fn veq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4986 let a = self.state[operands.src1].get_u32x4();
4987 let b = self.state[operands.src2].get_u32x4();
4988 let mut c = [0; 4];
4989 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
4990 *c = if a == b { u32::MAX } else { 0 };
4991 }
4992 self.state[operands.dst].set_u32x4(c);
4993 ControlFlow::Continue(())
4994 }
4995
4996 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
4997 fn vneq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
4998 let a = self.state[operands.src1].get_u32x4();
4999 let b = self.state[operands.src2].get_u32x4();
5000 let mut c = [0; 4];
5001 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5002 *c = if a != b { u32::MAX } else { 0 };
5003 }
5004 self.state[operands.dst].set_u32x4(c);
5005 ControlFlow::Continue(())
5006 }
5007
5008 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5009 fn vslt32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5010 let a = self.state[operands.src1].get_i32x4();
5011 let b = self.state[operands.src2].get_i32x4();
5012 let mut c = [0; 4];
5013 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5014 *c = if a < b { u32::MAX } else { 0 };
5015 }
5016 self.state[operands.dst].set_u32x4(c);
5017 ControlFlow::Continue(())
5018 }
5019
5020 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5021 fn vslteq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5022 let a = self.state[operands.src1].get_i32x4();
5023 let b = self.state[operands.src2].get_i32x4();
5024 let mut c = [0; 4];
5025 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5026 *c = if a <= b { u32::MAX } else { 0 };
5027 }
5028 self.state[operands.dst].set_u32x4(c);
5029 ControlFlow::Continue(())
5030 }
5031
5032 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5033 fn vult32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5034 let a = self.state[operands.src1].get_u32x4();
5035 let b = self.state[operands.src2].get_u32x4();
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 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5045 fn vulteq32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5046 let a = self.state[operands.src1].get_u32x4();
5047 let b = self.state[operands.src2].get_u32x4();
5048 let mut c = [0; 4];
5049 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5050 *c = if a <= b { u32::MAX } else { 0 };
5051 }
5052 self.state[operands.dst].set_u32x4(c);
5053 ControlFlow::Continue(())
5054 }
5055
5056 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5057 fn veq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5058 let a = self.state[operands.src1].get_u64x2();
5059 let b = self.state[operands.src2].get_u64x2();
5060 let mut c = [0; 2];
5061 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5062 *c = if a == b { u64::MAX } else { 0 };
5063 }
5064 self.state[operands.dst].set_u64x2(c);
5065 ControlFlow::Continue(())
5066 }
5067
5068 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5069 fn vneq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5070 let a = self.state[operands.src1].get_u64x2();
5071 let b = self.state[operands.src2].get_u64x2();
5072 let mut c = [0; 2];
5073 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5074 *c = if a != b { u64::MAX } else { 0 };
5075 }
5076 self.state[operands.dst].set_u64x2(c);
5077 ControlFlow::Continue(())
5078 }
5079
5080 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5081 fn vslt64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5082 let a = self.state[operands.src1].get_i64x2();
5083 let b = self.state[operands.src2].get_i64x2();
5084 let mut c = [0; 2];
5085 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5086 *c = if a < b { u64::MAX } else { 0 };
5087 }
5088 self.state[operands.dst].set_u64x2(c);
5089 ControlFlow::Continue(())
5090 }
5091
5092 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5093 fn vslteq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5094 let a = self.state[operands.src1].get_i64x2();
5095 let b = self.state[operands.src2].get_i64x2();
5096 let mut c = [0; 2];
5097 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5098 *c = if a <= b { u64::MAX } else { 0 };
5099 }
5100 self.state[operands.dst].set_u64x2(c);
5101 ControlFlow::Continue(())
5102 }
5103
5104 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5105 fn vult64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5106 let a = self.state[operands.src1].get_u64x2();
5107 let b = self.state[operands.src2].get_u64x2();
5108 let mut c = [0; 2];
5109 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5110 *c = if a < b { u64::MAX } else { 0 };
5111 }
5112 self.state[operands.dst].set_u64x2(c);
5113 ControlFlow::Continue(())
5114 }
5115
5116 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5117 fn vulteq64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5118 let a = self.state[operands.src1].get_u64x2();
5119 let b = self.state[operands.src2].get_u64x2();
5120 let mut c = [0; 2];
5121 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5122 *c = if a <= b { u64::MAX } else { 0 };
5123 }
5124 self.state[operands.dst].set_u64x2(c);
5125 ControlFlow::Continue(())
5126 }
5127
5128 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5129 fn vneg8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5130 let a = self.state[src].get_i8x16();
5131 self.state[dst].set_i8x16(a.map(|i| i.wrapping_neg()));
5132 ControlFlow::Continue(())
5133 }
5134
5135 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5136 fn vneg16x8(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5137 let a = self.state[src].get_i16x8();
5138 self.state[dst].set_i16x8(a.map(|i| i.wrapping_neg()));
5139 ControlFlow::Continue(())
5140 }
5141
5142 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5143 fn vneg32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5144 let a = self.state[src].get_i32x4();
5145 self.state[dst].set_i32x4(a.map(|i| i.wrapping_neg()));
5146 ControlFlow::Continue(())
5147 }
5148
5149 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5150 fn vneg64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5151 let a = self.state[src].get_i64x2();
5152 self.state[dst].set_i64x2(a.map(|i| i.wrapping_neg()));
5153 ControlFlow::Continue(())
5154 }
5155
5156 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5157 fn vnegf64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5158 let a = self.state[src].get_f64x2();
5159 self.state[dst].set_f64x2(a.map(|i| -i));
5160 ControlFlow::Continue(())
5161 }
5162
5163 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5164 fn vmin8x16_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5165 let mut a = self.state[operands.src1].get_i8x16();
5166 let b = self.state[operands.src2].get_i8x16();
5167 for (a, b) in a.iter_mut().zip(&b) {
5168 *a = (*a).min(*b);
5169 }
5170 self.state[operands.dst].set_i8x16(a);
5171 ControlFlow::Continue(())
5172 }
5173
5174 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5175 fn vmin8x16_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5176 let mut a = self.state[operands.src1].get_u8x16();
5177 let b = self.state[operands.src2].get_u8x16();
5178 for (a, b) in a.iter_mut().zip(&b) {
5179 *a = (*a).min(*b);
5180 }
5181 self.state[operands.dst].set_u8x16(a);
5182 ControlFlow::Continue(())
5183 }
5184
5185 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5186 fn vmin16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5187 let mut a = self.state[operands.src1].get_i16x8();
5188 let b = self.state[operands.src2].get_i16x8();
5189 for (a, b) in a.iter_mut().zip(&b) {
5190 *a = (*a).min(*b);
5191 }
5192 self.state[operands.dst].set_i16x8(a);
5193 ControlFlow::Continue(())
5194 }
5195
5196 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5197 fn vmin16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5198 let mut a = self.state[operands.src1].get_u16x8();
5199 let b = self.state[operands.src2].get_u16x8();
5200 for (a, b) in a.iter_mut().zip(&b) {
5201 *a = (*a).min(*b);
5202 }
5203 self.state[operands.dst].set_u16x8(a);
5204 ControlFlow::Continue(())
5205 }
5206
5207 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5208 fn vmin32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5209 let mut a = self.state[operands.src1].get_i32x4();
5210 let b = self.state[operands.src2].get_i32x4();
5211 for (a, b) in a.iter_mut().zip(&b) {
5212 *a = (*a).min(*b);
5213 }
5214 self.state[operands.dst].set_i32x4(a);
5215 ControlFlow::Continue(())
5216 }
5217
5218 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5219 fn vmin32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5220 let mut a = self.state[operands.src1].get_u32x4();
5221 let b = self.state[operands.src2].get_u32x4();
5222 for (a, b) in a.iter_mut().zip(&b) {
5223 *a = (*a).min(*b);
5224 }
5225 self.state[operands.dst].set_u32x4(a);
5226 ControlFlow::Continue(())
5227 }
5228
5229 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5230 fn vmax8x16_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5231 let mut a = self.state[operands.src1].get_i8x16();
5232 let b = self.state[operands.src2].get_i8x16();
5233 for (a, b) in a.iter_mut().zip(&b) {
5234 *a = (*a).max(*b);
5235 }
5236 self.state[operands.dst].set_i8x16(a);
5237 ControlFlow::Continue(())
5238 }
5239
5240 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5241 fn vmax8x16_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5242 let mut a = self.state[operands.src1].get_u8x16();
5243 let b = self.state[operands.src2].get_u8x16();
5244 for (a, b) in a.iter_mut().zip(&b) {
5245 *a = (*a).max(*b);
5246 }
5247 self.state[operands.dst].set_u8x16(a);
5248 ControlFlow::Continue(())
5249 }
5250
5251 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5252 fn vmax16x8_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5253 let mut a = self.state[operands.src1].get_i16x8();
5254 let b = self.state[operands.src2].get_i16x8();
5255 for (a, b) in a.iter_mut().zip(&b) {
5256 *a = (*a).max(*b);
5257 }
5258 self.state[operands.dst].set_i16x8(a);
5259 ControlFlow::Continue(())
5260 }
5261
5262 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5263 fn vmax16x8_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5264 let mut a = self.state[operands.src1].get_u16x8();
5265 let b = self.state[operands.src2].get_u16x8();
5266 for (a, b) in a.iter_mut().zip(&b) {
5267 *a = (*a).max(*b);
5268 }
5269 self.state[operands.dst].set_u16x8(a);
5270 ControlFlow::Continue(())
5271 }
5272
5273 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5274 fn vmax32x4_s(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5275 let mut a = self.state[operands.src1].get_i32x4();
5276 let b = self.state[operands.src2].get_i32x4();
5277 for (a, b) in a.iter_mut().zip(&b) {
5278 *a = (*a).max(*b);
5279 }
5280 self.state[operands.dst].set_i32x4(a);
5281 ControlFlow::Continue(())
5282 }
5283
5284 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5285 fn vmax32x4_u(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5286 let mut a = self.state[operands.src1].get_u32x4();
5287 let b = self.state[operands.src2].get_u32x4();
5288 for (a, b) in a.iter_mut().zip(&b) {
5289 *a = (*a).max(*b);
5290 }
5291 self.state[operands.dst].set_u32x4(a);
5292 ControlFlow::Continue(())
5293 }
5294
5295 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5296 fn vabs8x16(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5297 let a = self.state[src].get_i8x16();
5298 self.state[dst].set_i8x16(a.map(|i| i.wrapping_abs()));
5299 ControlFlow::Continue(())
5300 }
5301
5302 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5303 fn vabs16x8(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5304 let a = self.state[src].get_i16x8();
5305 self.state[dst].set_i16x8(a.map(|i| i.wrapping_abs()));
5306 ControlFlow::Continue(())
5307 }
5308
5309 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5310 fn vabs32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5311 let a = self.state[src].get_i32x4();
5312 self.state[dst].set_i32x4(a.map(|i| i.wrapping_abs()));
5313 ControlFlow::Continue(())
5314 }
5315
5316 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5317 fn vabs64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5318 let a = self.state[src].get_i64x2();
5319 self.state[dst].set_i64x2(a.map(|i| i.wrapping_abs()));
5320 ControlFlow::Continue(())
5321 }
5322
5323 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5324 fn vabsf32x4(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5325 let a = self.state[src].get_f32x4();
5326 self.state[dst].set_f32x4(a.map(|i| i.wasm_abs()));
5327 ControlFlow::Continue(())
5328 }
5329
5330 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5331 fn vabsf64x2(&mut self, dst: VReg, src: VReg) -> ControlFlow<Done> {
5332 let a = self.state[src].get_f64x2();
5333 self.state[dst].set_f64x2(a.map(|i| i.wasm_abs()));
5334 ControlFlow::Continue(())
5335 }
5336
5337 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5338 fn vmaximumf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5339 let mut a = self.state[operands.src1].get_f32x4();
5340 let b = self.state[operands.src2].get_f32x4();
5341 for (a, b) in a.iter_mut().zip(&b) {
5342 *a = a.wasm_maximum(*b);
5343 }
5344 self.state[operands.dst].set_f32x4(a);
5345 ControlFlow::Continue(())
5346 }
5347
5348 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5349 fn vmaximumf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5350 let mut a = self.state[operands.src1].get_f64x2();
5351 let b = self.state[operands.src2].get_f64x2();
5352 for (a, b) in a.iter_mut().zip(&b) {
5353 *a = a.wasm_maximum(*b);
5354 }
5355 self.state[operands.dst].set_f64x2(a);
5356 ControlFlow::Continue(())
5357 }
5358
5359 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5360 fn vminimumf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5361 let mut a = self.state[operands.src1].get_f32x4();
5362 let b = self.state[operands.src2].get_f32x4();
5363 for (a, b) in a.iter_mut().zip(&b) {
5364 *a = a.wasm_minimum(*b);
5365 }
5366 self.state[operands.dst].set_f32x4(a);
5367 ControlFlow::Continue(())
5368 }
5369
5370 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5371 fn vminimumf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5372 let mut a = self.state[operands.src1].get_f64x2();
5373 let b = self.state[operands.src2].get_f64x2();
5374 for (a, b) in a.iter_mut().zip(&b) {
5375 *a = a.wasm_minimum(*b);
5376 }
5377 self.state[operands.dst].set_f64x2(a);
5378 ControlFlow::Continue(())
5379 }
5380
5381 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5382 fn vshuffle(&mut self, dst: VReg, src1: VReg, src2: VReg, mask: u128) -> ControlFlow<Done> {
5383 let a = self.state[src1].get_u8x16();
5384 let b = self.state[src2].get_u8x16();
5385 let result = mask.to_le_bytes().map(|m| {
5386 if m < 16 {
5387 a[m as usize]
5388 } else {
5389 b[m as usize - 16]
5390 }
5391 });
5392 self.state[dst].set_u8x16(result);
5393 ControlFlow::Continue(())
5394 }
5395
5396 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5397 fn vswizzlei8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5398 let src1 = self.state[operands.src1].get_i8x16();
5399 let src2 = self.state[operands.src2].get_i8x16();
5400 let mut dst = [0i8; 16];
5401 for (i, &idx) in src2.iter().enumerate() {
5402 if (idx as usize) < 16 {
5403 dst[i] = src1[idx as usize];
5404 } else {
5405 dst[i] = 0
5406 }
5407 }
5408 self.state[operands.dst].set_i8x16(dst);
5409 ControlFlow::Continue(())
5410 }
5411
5412 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5413 fn vavground8x16(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5414 let mut a = self.state[operands.src1].get_u8x16();
5415 let b = self.state[operands.src2].get_u8x16();
5416 for (a, b) in a.iter_mut().zip(&b) {
5417 *a = ((u32::from(*a) + u32::from(*b) + 1) / 2) as u8;
5419 }
5420 self.state[operands.dst].set_u8x16(a);
5421 ControlFlow::Continue(())
5422 }
5423
5424 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5425 fn vavground16x8(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5426 let mut a = self.state[operands.src1].get_u16x8();
5427 let b = self.state[operands.src2].get_u16x8();
5428 for (a, b) in a.iter_mut().zip(&b) {
5429 *a = ((u32::from(*a) + u32::from(*b) + 1) / 2) as u16;
5431 }
5432 self.state[operands.dst].set_u16x8(a);
5433 ControlFlow::Continue(())
5434 }
5435
5436 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5437 fn veqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5438 let a = self.state[operands.src1].get_f32x4();
5439 let b = self.state[operands.src2].get_f32x4();
5440 let mut c = [0; 4];
5441 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5442 *c = if a == b { u32::MAX } else { 0 };
5443 }
5444 self.state[operands.dst].set_u32x4(c);
5445 ControlFlow::Continue(())
5446 }
5447
5448 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5449 fn vneqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5450 let a = self.state[operands.src1].get_f32x4();
5451 let b = self.state[operands.src2].get_f32x4();
5452 let mut c = [0; 4];
5453 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5454 *c = if a != b { u32::MAX } else { 0 };
5455 }
5456 self.state[operands.dst].set_u32x4(c);
5457 ControlFlow::Continue(())
5458 }
5459
5460 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5461 fn vltf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5462 let a = self.state[operands.src1].get_f32x4();
5463 let b = self.state[operands.src2].get_f32x4();
5464 let mut c = [0; 4];
5465 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5466 *c = if a < b { u32::MAX } else { 0 };
5467 }
5468 self.state[operands.dst].set_u32x4(c);
5469 ControlFlow::Continue(())
5470 }
5471
5472 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5473 fn vlteqf32x4(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5474 let a = self.state[operands.src1].get_f32x4();
5475 let b = self.state[operands.src2].get_f32x4();
5476 let mut c = [0; 4];
5477 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5478 *c = if a <= b { u32::MAX } else { 0 };
5479 }
5480 self.state[operands.dst].set_u32x4(c);
5481 ControlFlow::Continue(())
5482 }
5483
5484 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5485 fn veqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5486 let a = self.state[operands.src1].get_f64x2();
5487 let b = self.state[operands.src2].get_f64x2();
5488 let mut c = [0; 2];
5489 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5490 *c = if a == b { u64::MAX } else { 0 };
5491 }
5492 self.state[operands.dst].set_u64x2(c);
5493 ControlFlow::Continue(())
5494 }
5495
5496 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5497 fn vneqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5498 let a = self.state[operands.src1].get_f64x2();
5499 let b = self.state[operands.src2].get_f64x2();
5500 let mut c = [0; 2];
5501 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5502 *c = if a != b { u64::MAX } else { 0 };
5503 }
5504 self.state[operands.dst].set_u64x2(c);
5505 ControlFlow::Continue(())
5506 }
5507
5508 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5509 fn vltf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5510 let a = self.state[operands.src1].get_f64x2();
5511 let b = self.state[operands.src2].get_f64x2();
5512 let mut c = [0; 2];
5513 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5514 *c = if a < b { u64::MAX } else { 0 };
5515 }
5516 self.state[operands.dst].set_u64x2(c);
5517 ControlFlow::Continue(())
5518 }
5519
5520 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5521 fn vlteqf64x2(&mut self, operands: BinaryOperands<VReg>) -> ControlFlow<Done> {
5522 let a = self.state[operands.src1].get_f64x2();
5523 let b = self.state[operands.src2].get_f64x2();
5524 let mut c = [0; 2];
5525 for ((a, b), c) in a.iter().zip(&b).zip(&mut c) {
5526 *c = if a <= b { u64::MAX } else { 0 };
5527 }
5528 self.state[operands.dst].set_u64x2(c);
5529 ControlFlow::Continue(())
5530 }
5531
5532 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5533 fn vfma32x4(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
5534 let mut a = self.state[a].get_f32x4();
5535 let b = self.state[b].get_f32x4();
5536 let c = self.state[c].get_f32x4();
5537 for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
5538 *a = a.wasm_mul_add(b, c);
5539 }
5540 self.state[dst].set_f32x4(a);
5541 ControlFlow::Continue(())
5542 }
5543
5544 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5545 fn vfma64x2(&mut self, dst: VReg, a: VReg, b: VReg, c: VReg) -> ControlFlow<Done> {
5546 let mut a = self.state[a].get_f64x2();
5547 let b = self.state[b].get_f64x2();
5548 let c = self.state[c].get_f64x2();
5549 for ((a, b), c) in a.iter_mut().zip(b).zip(c) {
5550 *a = a.wasm_mul_add(b, c);
5551 }
5552 self.state[dst].set_f64x2(a);
5553 ControlFlow::Continue(())
5554 }
5555
5556 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5557 fn vselect(
5558 &mut self,
5559 dst: VReg,
5560 cond: XReg,
5561 if_nonzero: VReg,
5562 if_zero: VReg,
5563 ) -> ControlFlow<Done> {
5564 let result = if self.state[cond].get_u32() != 0 {
5565 self.state[if_nonzero]
5566 } else {
5567 self.state[if_zero]
5568 };
5569 self.state[dst] = result;
5570 ControlFlow::Continue(())
5571 }
5572
5573 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5574 fn xadd128(
5575 &mut self,
5576 dst_lo: XReg,
5577 dst_hi: XReg,
5578 lhs_lo: XReg,
5579 lhs_hi: XReg,
5580 rhs_lo: XReg,
5581 rhs_hi: XReg,
5582 ) -> ControlFlow<Done> {
5583 let lhs = self.get_i128(lhs_lo, lhs_hi);
5584 let rhs = self.get_i128(rhs_lo, rhs_hi);
5585 let result = lhs.wrapping_add(rhs);
5586 self.set_i128(dst_lo, dst_hi, result);
5587 ControlFlow::Continue(())
5588 }
5589
5590 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5591 fn xsub128(
5592 &mut self,
5593 dst_lo: XReg,
5594 dst_hi: XReg,
5595 lhs_lo: XReg,
5596 lhs_hi: XReg,
5597 rhs_lo: XReg,
5598 rhs_hi: XReg,
5599 ) -> ControlFlow<Done> {
5600 let lhs = self.get_i128(lhs_lo, lhs_hi);
5601 let rhs = self.get_i128(rhs_lo, rhs_hi);
5602 let result = lhs.wrapping_sub(rhs);
5603 self.set_i128(dst_lo, dst_hi, result);
5604 ControlFlow::Continue(())
5605 }
5606
5607 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5608 fn xwidemul64_s(
5609 &mut self,
5610 dst_lo: XReg,
5611 dst_hi: XReg,
5612 lhs: XReg,
5613 rhs: XReg,
5614 ) -> ControlFlow<Done> {
5615 let lhs = self.state[lhs].get_i64();
5616 let rhs = self.state[rhs].get_i64();
5617 let result = i128::from(lhs).wrapping_mul(i128::from(rhs));
5618 self.set_i128(dst_lo, dst_hi, result);
5619 ControlFlow::Continue(())
5620 }
5621
5622 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5623 fn xwidemul64_u(
5624 &mut self,
5625 dst_lo: XReg,
5626 dst_hi: XReg,
5627 lhs: XReg,
5628 rhs: XReg,
5629 ) -> ControlFlow<Done> {
5630 let lhs = self.state[lhs].get_u64();
5631 let rhs = self.state[rhs].get_u64();
5632 let result = u128::from(lhs).wrapping_mul(u128::from(rhs));
5633 self.set_i128(dst_lo, dst_hi, result as i128);
5634 ControlFlow::Continue(())
5635 }
5636
5637 fn xload16be_u32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
5641 let result = unsafe { self.load_ne::<u16, crate::XLoad16BeU32Z>(addr)? };
5642 self.state[dst].set_u32(u16::from_be(result).into());
5643 ControlFlow::Continue(())
5644 }
5645
5646 fn xload16be_s32_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
5647 let result = unsafe { self.load_ne::<i16, crate::XLoad16BeS32Z>(addr)? };
5648 self.state[dst].set_i32(i16::from_be(result).into());
5649 ControlFlow::Continue(())
5650 }
5651
5652 fn xload32be_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
5653 let result = unsafe { self.load_ne::<i32, crate::XLoad32BeZ>(addr)? };
5654 self.state[dst].set_i32(i32::from_be(result));
5655 ControlFlow::Continue(())
5656 }
5657
5658 fn xload64be_z(&mut self, dst: XReg, addr: AddrZ) -> ControlFlow<Done> {
5659 let result = unsafe { self.load_ne::<i64, crate::XLoad64BeZ>(addr)? };
5660 self.state[dst].set_i64(i64::from_be(result));
5661 ControlFlow::Continue(())
5662 }
5663
5664 fn xstore16be_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
5665 let val = self.state[val].get_u32() as u16;
5666 unsafe {
5667 self.store_ne::<u16, crate::XStore16BeZ>(addr, val.to_be())?;
5668 }
5669 ControlFlow::Continue(())
5670 }
5671
5672 fn xstore32be_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
5673 let val = self.state[val].get_u32();
5674 unsafe {
5675 self.store_ne::<u32, crate::XStore32BeZ>(addr, val.to_be())?;
5676 }
5677 ControlFlow::Continue(())
5678 }
5679
5680 fn xstore64be_z(&mut self, addr: AddrZ, val: XReg) -> ControlFlow<Done> {
5681 let val = self.state[val].get_u64();
5682 unsafe {
5683 self.store_ne::<u64, crate::XStore64BeZ>(addr, val.to_be())?;
5684 }
5685 ControlFlow::Continue(())
5686 }
5687
5688 fn fload32be_z(&mut self, dst: FReg, addr: AddrZ) -> ControlFlow<Done> {
5689 let val = unsafe { self.load_ne::<u32, crate::Fload32BeZ>(addr)? };
5690 self.state[dst].set_f32(f32::from_bits(u32::from_be(val)));
5691 ControlFlow::Continue(())
5692 }
5693
5694 fn fload64be_z(&mut self, dst: FReg, addr: AddrZ) -> ControlFlow<Done> {
5695 let val = unsafe { self.load_ne::<u64, crate::Fload64BeZ>(addr)? };
5696 self.state[dst].set_f64(f64::from_bits(u64::from_be(val)));
5697 ControlFlow::Continue(())
5698 }
5699
5700 fn fstore32be_z(&mut self, addr: AddrZ, src: FReg) -> ControlFlow<Done> {
5701 let val = self.state[src].get_f32();
5702 unsafe {
5703 self.store_ne::<u32, crate::Fstore32BeZ>(addr, val.to_bits().to_be())?;
5704 }
5705 ControlFlow::Continue(())
5706 }
5707
5708 fn fstore64be_z(&mut self, addr: AddrZ, src: FReg) -> ControlFlow<Done> {
5709 let val = self.state[src].get_f64();
5710 unsafe {
5711 self.store_ne::<u64, crate::Fstore64BeZ>(addr, val.to_bits().to_be())?;
5712 }
5713 ControlFlow::Continue(())
5714 }
5715
5716 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5717 fn vload128be_z(&mut self, dst: VReg, addr: AddrZ) -> ControlFlow<Done> {
5718 let val = unsafe { self.load_ne::<u128, crate::VLoad128BeZ>(addr)? };
5719 self.state[dst].set_u128(u128::from_be(val));
5720 ControlFlow::Continue(())
5721 }
5722
5723 #[interp_disable_if_cfg(pulley_disable_interp_simd)]
5724 fn vstore128be_z(&mut self, addr: AddrZ, src: VReg) -> ControlFlow<Done> {
5725 let val = self.state[src].get_u128();
5726 unsafe {
5727 self.store_ne::<u128, crate::Vstore128BeZ>(addr, val.to_be())?;
5728 }
5729 ControlFlow::Continue(())
5730 }
5731}