use crate::register::{
CastRegister, ConcatRegister, IndexableRegister, NumericRegister, Register, Storage,
reduced::{HalfRegister2, ReducedRegister},
};
use super::arch;
macro_rules! sat_clamp_narrow {
($from:ty, $fe:ty, $ie:ty) => {
#[inline(always)]
fn saturating_cast_from(value: Storage<$from>) -> Storage<Self> {
let lo = <$from as Register>::splat(<$ie>::MIN as $fe);
let hi = <$from as Register>::splat(<$ie>::MAX as $fe);
let clamped = <$from as NumericRegister>::min(<$from as NumericRegister>::max(value, lo), hi);
<Self as CastRegister<$from>>::cast_from(clamped)
}
};
}
pub type F32x2Wasm = HalfRegister2<super::F32x4Wasm>;
pub type I32x2Wasm = HalfRegister2<super::I32x4Wasm>;
pub type U32x2Wasm = HalfRegister2<super::U32x4Wasm>;
#[thermite_macros::inline_always]
impl ConcatRegister<f32> for F32x2Wasm {
fn concat(lo: Storage<f32>, hi: Storage<f32>) -> Storage<Self> {
ReducedRegister::new(arch::f32x4(lo, hi, 0.0, 0.0))
}
fn split(value: Storage<Self>) -> (Storage<f32>, Storage<f32>) {
(
arch::f32x4_extract_lane::<0>(value.0),
arch::f32x4_extract_lane::<1>(value.0),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<F32x2Wasm> for super::F32x4Wasm {
fn concat(lo: Storage<F32x2Wasm>, hi: Storage<F32x2Wasm>) -> Storage<Self> {
arch::i32x4_shuffle::<0, 1, 4, 5>(lo.0, hi.0)
}
fn split(value: Storage<Self>) -> (Storage<F32x2Wasm>, Storage<F32x2Wasm>) {
(
ReducedRegister::new(value),
ReducedRegister::new(arch::i32x4_shuffle::<2, 3, 2, 3>(value, value)),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<i32> for I32x2Wasm {
fn concat(lo: Storage<i32>, hi: Storage<i32>) -> Storage<Self> {
ReducedRegister::new(arch::i32x4(lo, hi, 0, 0))
}
fn split(value: Storage<Self>) -> (Storage<i32>, Storage<i32>) {
(
arch::i32x4_extract_lane::<0>(value.0),
arch::i32x4_extract_lane::<1>(value.0),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<I32x2Wasm> for super::I32x4Wasm {
fn concat(lo: Storage<I32x2Wasm>, hi: Storage<I32x2Wasm>) -> Storage<Self> {
arch::i32x4_shuffle::<0, 1, 4, 5>(lo.0, hi.0)
}
fn split(value: Storage<Self>) -> (Storage<I32x2Wasm>, Storage<I32x2Wasm>) {
(
ReducedRegister::new(value),
ReducedRegister::new(arch::i32x4_shuffle::<2, 3, 2, 3>(value, value)),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<u32> for U32x2Wasm {
fn concat(lo: Storage<u32>, hi: Storage<u32>) -> Storage<Self> {
ReducedRegister::new(arch::u32x4(lo, hi, 0, 0))
}
fn split(value: Storage<Self>) -> (Storage<u32>, Storage<u32>) {
(
arch::u32x4_extract_lane::<0>(value.0),
arch::u32x4_extract_lane::<1>(value.0),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<U32x2Wasm> for super::U32x4Wasm {
fn concat(lo: Storage<U32x2Wasm>, hi: Storage<U32x2Wasm>) -> Storage<Self> {
arch::i32x4_shuffle::<0, 1, 4, 5>(lo.0, hi.0)
}
fn split(value: Storage<Self>) -> (Storage<U32x2Wasm>, Storage<U32x2Wasm>) {
(
ReducedRegister::new(value),
ReducedRegister::new(arch::i32x4_shuffle::<2, 3, 2, 3>(value, value)),
)
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::F64x2Wasm> for F32x2Wasm {
fn cast_from(value: Storage<super::F64x2Wasm>) -> Storage<Self> {
ReducedRegister::new(arch::f32x4_demote_f64x2_zero(value))
}
}
#[thermite_macros::inline_always]
impl CastRegister<F32x2Wasm> for super::F64x2Wasm {
fn cast_from(value: Storage<F32x2Wasm>) -> Storage<Self> {
arch::f64x2_promote_low_f32x4(value.0)
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I64x2Wasm> for I32x2Wasm {
fn cast_from(value: Storage<super::I64x2Wasm>) -> Storage<Self> {
ReducedRegister::new(arch::i8x16_shuffle::<
0,
1,
2,
3, 8,
9,
10,
11, 0,
1,
2,
3, 8,
9,
10,
11, >(value, value))
}
sat_clamp_narrow!(super::I64x2Wasm, i64, i32);
}
#[thermite_macros::inline_always]
impl CastRegister<I32x2Wasm> for super::I64x2Wasm {
fn cast_from(value: Storage<I32x2Wasm>) -> Storage<Self> {
arch::i64x2_extend_low_i32x4(value.0)
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U64x2Wasm> for U32x2Wasm {
fn cast_from(value: Storage<super::U64x2Wasm>) -> Storage<Self> {
ReducedRegister::new(arch::i8x16_shuffle::<
0,
1,
2,
3, 8,
9,
10,
11, 0,
1,
2,
3, 8,
9,
10,
11, >(value, value))
}
sat_clamp_narrow!(super::U64x2Wasm, u64, u32);
}
#[thermite_macros::inline_always]
impl CastRegister<U32x2Wasm> for super::U64x2Wasm {
fn cast_from(value: Storage<U32x2Wasm>) -> Storage<Self> {
arch::u64x2_extend_low_u32x4(value.0)
}
}
#[thermite_macros::inline_always]
impl IndexableRegister<super::U64x2Wasm> for F32x2Wasm {}
impl IndexableRegister<super::U64x2Wasm> for I32x2Wasm {}
impl IndexableRegister<super::U64x2Wasm> for U32x2Wasm {}