use generic_array::typenum::U4;
use super::arch;
use crate::register::{
CastRegister, ConcatRegister, ExtendRegister, IndexableRegister, NumericRegister, Register, SaturatingCastRegister,
Storage, array::ArrayRegister, reduced::ReducedRegister,
};
macro_rules! sat_clamp_narrow16 {
($(($from:ty, $fe:ty, $into:ty, $ie:ty)),* $(,)?) => {$(
#[thermite_macros::inline_always]
impl SaturatingCastRegister<$from> for $into {
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)
}
}
)*};
}
sat_clamp_narrow16! {
(ArrayRegister<super::I64x2V2, 2>, i64, I16x4V2, i16),
(ArrayRegister<super::U64x2V2, 2>, u64, U16x4V2, u16),
(super::half::I32x2V2, i32, ArrayRegister<i16, 2>, i16),
(super::half::U32x2V2, u32, ArrayRegister<u16, 2>, u16),
(super::I64x2V2, i64, ArrayRegister<i16, 2>, i16),
(super::U64x2V2, u64, ArrayRegister<u16, 2>, u16),
(ArrayRegister<super::I64x2V2, 8>, i64, ArrayRegister<super::I16x8V2, 2>, i16),
(ArrayRegister<super::U64x2V2, 8>, u64, ArrayRegister<super::U16x8V2, 2>, u16),
}
pub type I16x4V2 = ReducedRegister<super::I16x8V2, U4>;
pub type U16x4V2 = ReducedRegister<super::U16x8V2, U4>;
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<i16, 2>> for I16x4V2 {
fn concat(lo: Storage<ArrayRegister<i16, 2>>, hi: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi16(lo.0[0], lo.0[1], hi.0[0], hi.0[1], 0, 0, 0, 0) })
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<i16, 2>>, Storage<ArrayRegister<i16, 2>>) {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
(ArrayRegister([arr[0], arr[1]]), ArrayRegister([arr[2], arr[3]]))
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<i16, 2>> for I16x4V2 {
fn extend(value: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi16(value.0[0], value.0[1], 0, 0, 0, 0, 0, 0) })
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<i16, 2>> {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0], arr[1]])
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<u16, 2>> for U16x4V2 {
fn concat(lo: Storage<ArrayRegister<u16, 2>>, hi: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi16(
lo.0[0] as i16,
lo.0[1] as i16,
hi.0[0] as i16,
hi.0[1] as i16,
0,
0,
0,
0,
)
})
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<u16, 2>>, Storage<ArrayRegister<u16, 2>>) {
let mut arr = [0u16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
(ArrayRegister([arr[0], arr[1]]), ArrayRegister([arr[2], arr[3]]))
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<u16, 2>> for U16x4V2 {
fn extend(value: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi16(value.0[0] as i16, value.0[1] as i16, 0, 0, 0, 0, 0, 0) })
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<u16, 2>> {
let mut arr = [0u16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0], arr[1]])
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<I16x4V2> for super::I16x8V2 {
fn concat(lo: Storage<I16x4V2>, hi: Storage<I16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_unpacklo_epi64(lo.0, hi.0) }
}
fn split(value: Storage<Self>) -> (Storage<I16x4V2>, Storage<I16x4V2>) {
(
ReducedRegister::new(value),
ReducedRegister::new(unsafe { arch::_mm_unpackhi_epi64(value, value) }),
)
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<U16x4V2> for super::U16x8V2 {
fn concat(lo: Storage<U16x4V2>, hi: Storage<U16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_unpacklo_epi64(lo.0, hi.0) }
}
fn split(value: Storage<Self>) -> (Storage<U16x4V2>, Storage<U16x4V2>) {
(
ReducedRegister::new(value),
ReducedRegister::new(unsafe { arch::_mm_unpackhi_epi64(value, value) }),
)
}
}
#[thermite_macros::inline_always]
impl CastRegister<I16x4V2> for super::I32x4V2 {
fn cast_from(value: Storage<I16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi16_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U16x4V2> for super::U32x4V2 {
fn cast_from(value: Storage<U16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_cvtepu16_epi32(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I32x4V2> for I16x4V2 {
fn cast_from(value: Storage<super::I32x4V2>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_shuffle_epi8(
value,
arch::_mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1),
)
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U32x4V2> for U16x4V2 {
fn cast_from(value: Storage<super::U32x4V2>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_shuffle_epi8(
value,
arch::_mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1),
)
})
}
}
#[thermite_macros::inline_always]
impl SaturatingCastRegister<super::I32x4V2> for I16x4V2 {
fn saturating_cast_from(value: Storage<super::I32x4V2>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_packs_epi32(value, value) })
}
}
#[thermite_macros::inline_always]
impl SaturatingCastRegister<super::U32x4V2> for U16x4V2 {
fn saturating_cast_from(value: Storage<super::U32x4V2>) -> Storage<Self> {
let clamped = unsafe { arch::_mm_min_epu32(value, arch::_mm_set1_epi32(0xFFFF)) };
ReducedRegister::new(unsafe { arch::_mm_packus_epi32(clamped, clamped) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i16, 2>> for super::half::I32x2V2 {
fn cast_from(value: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u16, 2>> for super::half::U32x2V2 {
fn cast_from(value: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe { arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::I32x2V2> for ArrayRegister<i16, 2> {
fn cast_from(value: Storage<super::half::I32x2V2>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] as i16, arr[1] as i16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::U32x2V2> for ArrayRegister<u16, 2> {
fn cast_from(value: Storage<super::half::U32x2V2>) -> Storage<Self> {
let mut arr = [0u32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] as u16, arr[1] as u16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i16, 2>> for super::I64x2V2 {
fn cast_from(value: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
unsafe { arch::_mm_set_epi64x(value.0[1] as i64, value.0[0] as i64) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u16, 2>> for super::U64x2V2 {
fn cast_from(value: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
unsafe { arch::_mm_set_epi64x(value.0[1] as i64, value.0[0] as i64) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I64x2V2> for ArrayRegister<i16, 2> {
fn cast_from(value: Storage<super::I64x2V2>) -> Storage<Self> {
let mut arr = [0i64; 2];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value) };
ArrayRegister([arr[0] as i16, arr[1] as i16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U64x2V2> for ArrayRegister<u16, 2> {
fn cast_from(value: Storage<super::U64x2V2>) -> Storage<Self> {
let mut arr = [0u64; 2];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value) };
ArrayRegister([arr[0] as u16, arr[1] as u16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<I16x4V2> for ArrayRegister<super::I64x2V2, 2> {
fn cast_from(value: Storage<I16x4V2>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm_cvtepi16_epi64(value.0),
arch::_mm_cvtepi16_epi64(arch::_mm_srli_si128(value.0, 4)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<U16x4V2> for ArrayRegister<super::U64x2V2, 2> {
fn cast_from(value: Storage<U16x4V2>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm_cvtepu16_epi64(value.0),
arch::_mm_cvtepu16_epi64(arch::_mm_srli_si128(value.0, 4)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I64x2V2, 2>> for I16x4V2 {
fn cast_from(value: Storage<ArrayRegister<super::I64x2V2, 2>>) -> Storage<Self> {
unsafe {
let mask = arch::_mm_narrow_qword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(value.0[0], mask); let hi = arch::_mm_shuffle_epi8(value.0[1], mask);
ReducedRegister::new(arch::_mm_unpacklo_epi32(lo, hi))
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U64x2V2, 2>> for U16x4V2 {
fn cast_from(value: Storage<ArrayRegister<super::U64x2V2, 2>>) -> Storage<Self> {
unsafe {
let mask = arch::_mm_narrow_qword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(value.0[0], mask);
let hi = arch::_mm_shuffle_epi8(value.0[1], mask);
ReducedRegister::new(arch::_mm_unpacklo_epi32(lo, hi))
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I16x8V2> for ArrayRegister<super::I64x2V2, 4> {
fn cast_from(value: Storage<super::I16x8V2>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm_cvtepi16_epi64(value),
arch::_mm_cvtepi16_epi64(arch::_mm_srli_si128(value, 4)),
arch::_mm_cvtepi16_epi64(arch::_mm_srli_si128(value, 8)),
arch::_mm_cvtepi16_epi64(arch::_mm_srli_si128(value, 12)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U16x8V2> for ArrayRegister<super::U64x2V2, 4> {
fn cast_from(value: Storage<super::U16x8V2>) -> Storage<Self> {
unsafe {
ArrayRegister([
arch::_mm_cvtepu16_epi64(value),
arch::_mm_cvtepu16_epi64(arch::_mm_srli_si128(value, 4)),
arch::_mm_cvtepu16_epi64(arch::_mm_srli_si128(value, 8)),
arch::_mm_cvtepu16_epi64(arch::_mm_srli_si128(value, 12)),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I64x2V2, 4>> for super::I16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::I64x2V2, 4>>) -> Storage<Self> {
unsafe { arch::_mm_cvt4epi64_epi16x_v2(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U64x2V2, 4>> for super::U16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::U64x2V2, 4>>) -> Storage<Self> {
unsafe { arch::_mm_cvt4epi64_epi16x_v2(value.0) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I16x8V2, 2>> for ArrayRegister<super::I64x2V2, 8> {
fn cast_from(value: Storage<ArrayRegister<super::I16x8V2, 2>>) -> Storage<Self> {
let (lo, hi) = unsafe {
(
arch::_mm_cvtepi16_4epi64x_v2(value.0[0]),
arch::_mm_cvtepi16_4epi64x_v2(value.0[1]),
)
};
ArrayRegister([lo[0], lo[1], lo[2], lo[3], hi[0], hi[1], hi[2], hi[3]])
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U16x8V2, 2>> for ArrayRegister<super::U64x2V2, 8> {
fn cast_from(value: Storage<ArrayRegister<super::U16x8V2, 2>>) -> Storage<Self> {
let (lo, hi) = unsafe {
(
arch::_mm_cvtepu16_4epi64x_v2(value.0[0]),
arch::_mm_cvtepu16_4epi64x_v2(value.0[1]),
)
};
ArrayRegister([lo[0], lo[1], lo[2], lo[3], hi[0], hi[1], hi[2], hi[3]])
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I64x2V2, 8>> for ArrayRegister<super::I16x8V2, 2> {
fn cast_from(value: Storage<ArrayRegister<super::I64x2V2, 8>>) -> Storage<Self> {
let v = value.0;
unsafe {
ArrayRegister([
arch::_mm_cvt4epi64_epi16x_v2([v[0], v[1], v[2], v[3]]),
arch::_mm_cvt4epi64_epi16x_v2([v[4], v[5], v[6], v[7]]),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U64x2V2, 8>> for ArrayRegister<super::U16x8V2, 2> {
fn cast_from(value: Storage<ArrayRegister<super::U64x2V2, 8>>) -> Storage<Self> {
let v = value.0;
unsafe {
ArrayRegister([
arch::_mm_cvt4epi64_epi16x_v2([v[0], v[1], v[2], v[3]]),
arch::_mm_cvt4epi64_epi16x_v2([v[4], v[5], v[6], v[7]]),
])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i16, 2>> for super::half::F32x2V2 {
fn cast_from(value: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_cvtepi32_ps(arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0))
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u16, 2>> for super::half::F32x2V2 {
fn cast_from(value: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_cvtepi32_ps(arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0))
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::F32x2V2> for ArrayRegister<i16, 2> {
fn cast_from(value: Storage<super::half::F32x2V2>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, arch::_mm_cvttps_epi32(value.0)) };
ArrayRegister([arr[0] as i16, arr[1] as i16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::half::F32x2V2> for ArrayRegister<u16, 2> {
fn cast_from(value: Storage<super::half::F32x2V2>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, arch::_mm_cvttps_epi32(value.0)) };
ArrayRegister([arr[0] as u16, arr[1] as u16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<i16, 2>> for super::F64x2V2 {
fn cast_from(value: Storage<ArrayRegister<i16, 2>>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi32_pd(arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0)) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<u16, 2>> for super::F64x2V2 {
fn cast_from(value: Storage<ArrayRegister<u16, 2>>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi32_pd(arch::_mm_setr_epi32(value.0[0] as i32, value.0[1] as i32, 0, 0)) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::F64x2V2> for ArrayRegister<i16, 2> {
fn cast_from(value: Storage<super::F64x2V2>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, arch::_mm_cvttpd_epi32(value)) };
ArrayRegister([arr[0] as i16, arr[1] as i16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::F64x2V2> for ArrayRegister<u16, 2> {
fn cast_from(value: Storage<super::F64x2V2>) -> Storage<Self> {
let mut arr = [0i32; 4];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, arch::_mm_cvttpd_epi32(value)) };
ArrayRegister([arr[0] as u16, arr[1] as u16])
}
}
#[thermite_macros::inline_always]
impl CastRegister<I16x4V2> for super::F32x4V2 {
fn cast_from(value: Storage<I16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi32_ps(arch::_mm_cvtepi16_epi32(value.0)) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<U16x4V2> for super::F32x4V2 {
fn cast_from(value: Storage<U16x4V2>) -> Storage<Self> {
unsafe { arch::_mm_cvtepi32_ps(arch::_mm_cvtepu16_epi32(value.0)) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::F32x4V2> for I16x4V2 {
fn cast_from(value: Storage<super::F32x4V2>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value), arch::_mm_narrow_dword_to_word_maskx_v2())
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::F32x4V2> for U16x4V2 {
fn cast_from(value: Storage<super::F32x4V2>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value), arch::_mm_narrow_dword_to_word_maskx_v2())
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<I16x4V2> for ArrayRegister<super::F64x2V2, 2> {
fn cast_from(value: Storage<I16x4V2>) -> Storage<Self> {
ArrayRegister(unsafe { arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(value.0)) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<U16x4V2> for ArrayRegister<super::F64x2V2, 2> {
fn cast_from(value: Storage<U16x4V2>) -> Storage<Self> {
ArrayRegister(unsafe { arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(value.0)) })
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 2>> for I16x4V2 {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
let i32s = arch::_mm_cvtt2pd_epi32x_v2(value.0);
arch::_mm_shuffle_epi8(i32s, arch::_mm_narrow_dword_to_word_maskx_v2())
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 2>> for U16x4V2 {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
let i32s = arch::_mm_cvtt2pd_epi32x_v2(value.0);
arch::_mm_shuffle_epi8(i32s, arch::_mm_narrow_dword_to_word_maskx_v2())
})
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I16x8V2> for ArrayRegister<super::F32x4V2, 2> {
fn cast_from(value: Storage<super::I16x8V2>) -> Storage<Self> {
unsafe {
let lo = arch::_mm_cvtepi32_ps(arch::_mm_cvtepi16_epi32(value));
let hi = arch::_mm_cvtepi32_ps(arch::_mm_cvtepi16_epi32(arch::_mm_srli_si128(value, 8)));
ArrayRegister([lo, hi])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U16x8V2> for ArrayRegister<super::F32x4V2, 2> {
fn cast_from(value: Storage<super::U16x8V2>) -> Storage<Self> {
unsafe {
let lo = arch::_mm_cvtepi32_ps(arch::_mm_cvtepu16_epi32(value));
let hi = arch::_mm_cvtepi32_ps(arch::_mm_cvtepu16_epi32(arch::_mm_srli_si128(value, 8)));
ArrayRegister([lo, hi])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F32x4V2, 2>> for super::I16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::F32x4V2, 2>>) -> Storage<Self> {
unsafe {
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value.0[0]), mask); let hi = arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value.0[1]), mask);
arch::_mm_unpacklo_epi64(lo, hi) }
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F32x4V2, 2>> for super::U16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::F32x4V2, 2>>) -> Storage<Self> {
unsafe {
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value.0[0]), mask);
let hi = arch::_mm_shuffle_epi8(arch::_mm_cvttps_epi32(value.0[1]), mask);
arch::_mm_unpacklo_epi64(lo, hi)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::I16x8V2> for ArrayRegister<super::F64x2V2, 4> {
fn cast_from(value: Storage<super::I16x8V2>) -> Storage<Self> {
unsafe {
let lo = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(value));
let hi = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(arch::_mm_srli_si128(value, 8)));
ArrayRegister([lo[0], lo[1], hi[0], hi[1]])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<super::U16x8V2> for ArrayRegister<super::F64x2V2, 4> {
fn cast_from(value: Storage<super::U16x8V2>) -> Storage<Self> {
unsafe {
let lo = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(value));
let hi = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(arch::_mm_srli_si128(value, 8)));
ArrayRegister([lo[0], lo[1], hi[0], hi[1]])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 4>> for super::I16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 4>>) -> Storage<Self> {
let v = value.0;
unsafe {
let lo = arch::_mm_cvtt2pd_epi32x_v2([v[0], v[1]]);
let hi = arch::_mm_cvtt2pd_epi32x_v2([v[2], v[3]]);
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(lo, mask);
let hi = arch::_mm_shuffle_epi8(hi, mask);
arch::_mm_unpacklo_epi64(lo, hi)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 4>> for super::U16x8V2 {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 4>>) -> Storage<Self> {
let v = value.0;
unsafe {
let lo = arch::_mm_cvtt2pd_epi32x_v2([v[0], v[1]]);
let hi = arch::_mm_cvtt2pd_epi32x_v2([v[2], v[3]]);
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo = arch::_mm_shuffle_epi8(lo, mask);
let hi = arch::_mm_shuffle_epi8(hi, mask);
arch::_mm_unpacklo_epi64(lo, hi)
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::I16x8V2, 2>> for ArrayRegister<super::F64x2V2, 8> {
fn cast_from(value: Storage<ArrayRegister<super::I16x8V2, 2>>) -> Storage<Self> {
unsafe {
let v0 = value.0[0];
let v1 = value.0[1];
let a = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(v0));
let b = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(arch::_mm_srli_si128(v0, 8)));
let c = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(v1));
let d = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepi16_epi32(arch::_mm_srli_si128(v1, 8)));
ArrayRegister([a[0], a[1], b[0], b[1], c[0], c[1], d[0], d[1]])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::U16x8V2, 2>> for ArrayRegister<super::F64x2V2, 8> {
fn cast_from(value: Storage<ArrayRegister<super::U16x8V2, 2>>) -> Storage<Self> {
unsafe {
let v0 = value.0[0];
let v1 = value.0[1];
let a = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(v0));
let b = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(arch::_mm_srli_si128(v0, 8)));
let c = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(v1));
let d = arch::_mm_cvtepi32_2pdx_v2(arch::_mm_cvtepu16_epi32(arch::_mm_srli_si128(v1, 8)));
ArrayRegister([a[0], a[1], b[0], b[1], c[0], c[1], d[0], d[1]])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 8>> for ArrayRegister<super::I16x8V2, 2> {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 8>>) -> Storage<Self> {
let v = value.0;
unsafe {
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo0 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[0], v[1]]), mask);
let lo1 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[2], v[3]]), mask);
let hi0 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[4], v[5]]), mask);
let hi1 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[6], v[7]]), mask);
ArrayRegister([arch::_mm_unpacklo_epi64(lo0, lo1), arch::_mm_unpacklo_epi64(hi0, hi1)])
}
}
}
#[thermite_macros::inline_always]
impl CastRegister<ArrayRegister<super::F64x2V2, 8>> for ArrayRegister<super::U16x8V2, 2> {
fn cast_from(value: Storage<ArrayRegister<super::F64x2V2, 8>>) -> Storage<Self> {
let v = value.0;
unsafe {
let mask = arch::_mm_narrow_dword_to_word_maskx_v2();
let lo0 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[0], v[1]]), mask);
let lo1 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[2], v[3]]), mask);
let hi0 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[4], v[5]]), mask);
let hi1 = arch::_mm_shuffle_epi8(arch::_mm_cvtt2pd_epi32x_v2([v[6], v[7]]), mask);
ArrayRegister([arch::_mm_unpacklo_epi64(lo0, lo1), arch::_mm_unpacklo_epi64(hi0, hi1)])
}
}
}
#[inline(always)]
fn bool_to_i16_mask(b: bool) -> i16 {
if b { !0 } else { 0 }
}
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<bool, 2>> for I16x4V2 {
fn concat(lo: Storage<ArrayRegister<bool, 2>>, hi: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi16(
bool_to_i16_mask(lo.0[0]),
bool_to_i16_mask(lo.0[1]),
bool_to_i16_mask(hi.0[0]),
bool_to_i16_mask(hi.0[1]),
0,
0,
0,
0,
)
})
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<bool, 2>>, Storage<ArrayRegister<bool, 2>>) {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
(
ArrayRegister([arr[0] != 0, arr[1] != 0]),
ArrayRegister([arr[2] != 0, arr[3] != 0]),
)
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<bool, 2>> for I16x4V2 {
fn extend(value: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi16(
bool_to_i16_mask(value.0[0]),
bool_to_i16_mask(value.0[1]),
0,
0,
0,
0,
0,
0,
)
})
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<bool, 2>> {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] != 0, arr[1] != 0])
}
}
#[thermite_macros::inline_always]
impl ConcatRegister<ArrayRegister<bool, 2>> for U16x4V2 {
fn concat(lo: Storage<ArrayRegister<bool, 2>>, hi: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi16(
bool_to_i16_mask(lo.0[0]),
bool_to_i16_mask(lo.0[1]),
bool_to_i16_mask(hi.0[0]),
bool_to_i16_mask(hi.0[1]),
0,
0,
0,
0,
)
})
}
fn split(value: Storage<Self>) -> (Storage<ArrayRegister<bool, 2>>, Storage<ArrayRegister<bool, 2>>) {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
(
ArrayRegister([arr[0] != 0, arr[1] != 0]),
ArrayRegister([arr[2] != 0, arr[3] != 0]),
)
}
}
#[thermite_macros::inline_always]
impl ExtendRegister<ArrayRegister<bool, 2>> for U16x4V2 {
fn extend(value: Storage<ArrayRegister<bool, 2>>) -> Storage<Self> {
ReducedRegister::new(unsafe {
arch::_mm_setr_epi16(
bool_to_i16_mask(value.0[0]),
bool_to_i16_mask(value.0[1]),
0,
0,
0,
0,
0,
0,
)
})
}
fn narrow(value: Storage<Self>) -> Storage<ArrayRegister<bool, 2>> {
let mut arr = [0i16; 8];
unsafe { arch::_mm_storeu_si128(arr.as_mut_ptr() as *mut _, value.0) };
ArrayRegister([arr[0] != 0, arr[1] != 0])
}
}
impl IndexableRegister<<super::super::X86V2 as crate::simd::Simd>::u32x4> for I16x4V2 {}
impl IndexableRegister<<super::super::X86V2 as crate::simd::Simd>::u32x4> for U16x4V2 {}
impl IndexableRegister<<super::super::X86V2 as crate::simd::Simd>::u64x4> for I16x4V2 {}
impl IndexableRegister<<super::super::X86V2 as crate::simd::Simd>::u64x4> for U16x4V2 {}