#![allow(clippy::identity_op, unsafe_op_in_unsafe_fn, clippy::missing_safety_doc)]
pub use super::arch::*;
pub mod bits;
pub mod casts;
pub mod cmp;
pub mod math;
pub use bits::*;
pub use casts::*;
pub use cmp::*;
pub use math::*;
pub use crate::backend::generic::polyfills::*;
#[inline(always)]
pub const fn identity<T>(value: T) -> T {
value
}
#[rustfmt::skip]
#[inline(always)]
pub const fn x4indices(a: u8, b: u8, c: u8, d: u8) -> v128 {
u8x16(
a * 4, a * 4 + 1, a * 4 + 2, a * 4 + 3, b * 4, b * 4 + 1, b * 4 + 2, b * 4 + 3, c * 4, c * 4 + 1, c * 4 + 2, c * 4 + 3, d * 4, d * 4 + 1, d * 4 + 2, d * 4 + 3, )
}
#[rustfmt::skip]
#[inline(always)]
pub const fn x2indices(a: u8, b: u8) -> v128 {
u8x16(
a * 8, a * 8 + 1, a * 8 + 2, a * 8 + 3,
a * 8 + 4, a * 8 + 5, a * 8 + 6, a * 8 + 7,
b * 8, b * 8 + 1, b * 8 + 2, b * 8 + 3,
b * 8 + 4, b * 8 + 5, b * 8 + 6, b * 8 + 7,
)
}
const fn lane_expand_pattern(elem: usize) -> [u8; 16] {
let mut o = [0u8; 16];
let mut j = 0;
while j < 16 {
o[j] = (j / elem) as u8;
j += 1;
}
o
}
const fn lane_offset_pattern(elem: usize) -> [u8; 16] {
let mut o = [0u8; 16];
let mut j = 0;
while j < 16 {
o[j] = (j % elem) as u8;
j += 1;
}
o
}
#[inline(always)]
pub fn wasm_lane_table_dyn<const N: usize>(idxs: [u32; N]) -> v128 {
let p = idxs.as_ptr();
let lim = u32x4_splat(N as u32);
let bytes = unsafe {
if const { N == 16 } {
let a = u32x4_min(v128_load(p as *const v128), lim);
let b = u32x4_min(v128_load(p.add(4) as *const v128), lim);
let c = u32x4_min(v128_load(p.add(8) as *const v128), lim);
let d = u32x4_min(v128_load(p.add(12) as *const v128), lim);
u8x16_narrow_i16x8(u16x8_narrow_i32x4(a, b), u16x8_narrow_i32x4(c, d))
} else if const { N == 8 } {
let a = u32x4_min(v128_load(p as *const v128), lim);
let b = u32x4_min(v128_load(p.add(4) as *const v128), lim);
let w = u16x8_narrow_i32x4(a, b);
u8x16_narrow_i16x8(w, w)
} else if const { N == 4 } {
let a = u32x4_min(v128_load(p as *const v128), lim);
let w = u16x8_narrow_i32x4(a, a);
u8x16_narrow_i16x8(w, w)
} else {
let a = u32x4_min(v128_load64_zero(p as *const u64), lim);
let w = u16x8_narrow_i32x4(a, a);
u8x16_narrow_i16x8(w, w)
}
};
if const { N == 16 } {
return bytes;
}
wasm_lane_expand::<N>(bytes)
}
#[inline(always)]
fn wasm_lane_expand<const N: usize>(bytes: v128) -> v128 {
if const { N == 16 } {
return bytes;
}
let expanded = u8x16_swizzle(bytes, const { u8x16_from_bytes(lane_expand_pattern(16 / N)) });
let scaled = u8x16_shl(expanded, const { (16 / N).trailing_zeros() });
u8x16_add(scaled, const { u8x16_from_bytes(lane_offset_pattern(16 / N)) })
}
#[inline(always)]
pub unsafe fn wasm_lane_table_row<const N: usize>(row: *const u8) -> v128 {
wasm_lane_expand::<N>(unsafe { v128_load64_zero(row as *const u64) })
}
#[inline(always)]
pub const fn u8x16_from_bytes(b: [u8; 16]) -> v128 {
u8x16(
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15],
)
}
#[inline(always)]
pub const fn imm8x2_to_indices<const IMM8: i32>() -> v128 {
x2indices(((IMM8 >> 0) & 0b1) as u8, ((IMM8 >> 1) & 0b1) as u8)
}
#[inline(always)]
pub const fn imm8x4_to_indices<const IMM8: i32>() -> v128 {
x4indices(
((IMM8 >> 0) & 0b11) as u8,
((IMM8 >> 2) & 0b11) as u8,
((IMM8 >> 4) & 0b11) as u8,
((IMM8 >> 6) & 0b11) as u8,
)
}
#[inline(always)]
pub const fn imm8x2_to_mask<const IMM8: i32>() -> v128 {
let a = -(((IMM8 >> 0) & 0b1) as i8);
let b = -(((IMM8 >> 1) & 0b1) as i8);
i8x16(
a, a, a, a, a, a, a, a, b, b, b, b, b, b, b, b, )
}
#[inline(always)]
pub const fn imm8x4_to_mask<const IMM8: i32>() -> v128 {
let a = -(((IMM8 >> 0) & 0b1) as i8);
let b = -(((IMM8 >> 1) & 0b1) as i8);
let c = -(((IMM8 >> 2) & 0b1) as i8);
let d = -(((IMM8 >> 3) & 0b1) as i8);
i8x16(
a, a, a, a, b, b, b, b, c, c, c, c, d, d, d, d, )
}