#![allow(clippy::indexing_slicing)]
mod bit;
mod cvt;
mod farith;
mod fcmp;
mod iarith;
mod iarith2;
mod icmp;
mod lane;
mod lanes;
mod mem;
mod relaxed;
use super::Execution;
use crate::instance::Instance;
use crate::module::op_simd::SimdOp;
use crate::store::StoreInner;
use crate::value::{Val, V128};
use crate::Result;
impl Execution {
pub(super) fn exec_simd(
&mut self,
inner: &mut StoreInner,
code: &crate::module::code::Code,
s: &SimdOp,
instance: Instance,
) -> Result<()> {
if self.exec_simd_mem(inner, code, s, instance)? {
return Ok(());
}
self.exec_simd_compute(s)
}
fn exec_simd_compute(&mut self, s: &SimdOp) -> Result<()> {
self.exec_simd_lane(s)
}
#[inline]
fn pop_v128(&mut self) -> Result<u128> {
Ok(self.pop_v128_cell()?.unwrap_v128().as_u128())
}
#[inline]
fn push_v128(&mut self, v: u128) {
self.push(Val::V128(V128::from(v)));
}
fn v_binop<T: Copy, const N: usize>(
&mut self,
split: fn(u128) -> [T; N],
join: fn([T; N]) -> u128,
f: impl Fn(T, T) -> T,
) -> Result<()> {
let b = self.pop_v128()?;
let a = self.pop_v128()?;
self.push_v128(join(lanes::zip(split(a), split(b), f)));
Ok(())
}
fn v_unop<T: Copy, U, const N: usize>(
&mut self,
split: fn(u128) -> [T; N],
join: fn([U; N]) -> u128,
f: impl Fn(T) -> U,
) -> Result<()> {
let a = self.pop_v128()?;
self.push_v128(join(lanes::map(split(a), f)));
Ok(())
}
fn v_cmp<T: Copy, const N: usize>(
&mut self,
split: fn(u128) -> [T; N],
f: impl Fn(T, T) -> bool,
) -> Result<()> {
let b = self.pop_v128()?;
let a = self.pop_v128()?;
let (la, lb) = (split(a), split(b));
let mask: [bool; N] = core::array::from_fn(|i| f(la[i], lb[i]));
self.push_v128(cmp_mask(mask));
Ok(())
}
fn v_shift<T: Copy, const N: usize>(
&mut self,
split: fn(u128) -> [T; N],
join: fn([T; N]) -> u128,
f: impl Fn(T, u32) -> T,
) -> Result<()> {
let count = self.pop_i32()? as u32;
let a = self.pop_v128()?;
let s = count % (128 / N as u32);
self.push_v128(join(lanes::map(split(a), |x| f(x, s))));
Ok(())
}
}
fn cmp_mask<const N: usize>(mask: [bool; N]) -> u128 {
let w = 16 / N;
let mut b = [0u8; 16];
for i in 0..N {
if mask[i] {
for k in 0..w {
b[i * w + k] = 0xff;
}
}
}
u128::from_le_bytes(b)
}