use super::arch;
pub mod f32x4;
pub mod i32x4;
pub mod u32x4;
pub mod f64x2;
pub mod i64x2;
pub mod u64x2;
pub mod i16x8;
pub mod u16x8;
pub mod i8x16;
pub mod u8x16;
pub mod half;
pub mod half16;
pub mod half8; pub mod packed;
pub use f32x4::F32x4V1;
pub use i32x4::I32x4V1;
pub use u32x4::U32x4V1;
pub use f64x2::F64x2V1;
pub use i64x2::I64x2V1;
pub use u64x2::U64x2V1;
pub use i16x8::I16x8V1;
pub use u16x8::U16x8V1;
pub use i8x16::I8x16V1;
pub use u8x16::U8x16V1;
impl_newregister!(
F32x4V1, I32x4V1, U32x4V1, F64x2V1, I64x2V1, U64x2V1, I16x8V1, U16x8V1, I8x16V1, U8x16V1
);
use crate::{
element::FindUSize,
isa::InstructionSet,
register::{IndexableRegister, Storage, array::ArrayRegister},
simd::{HasIsa, NativeIsa, NativeSimd, Simd, Simd3, Simd3A},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct X86V1;
impl HasIsa for X86V1 {
type Native = Self;
const ISA: InstructionSet = InstructionSet::X86V1;
}
#[thermite_macros::inline_always]
impl NativeIsa for X86V1 {
type Registers = generic_array::typenum::U8;
type Native32Width = generic_array::typenum::U4;
type Native64Width = generic_array::typenum::U2;
type Native16Width = generic_array::typenum::U8;
type Native8Width = generic_array::typenum::U16;
type NativeAlignment = crate::simd::Align16;
const HAS_PREFETCH: bool = arch::HAS_PREFETCH;
fn prefetch<const LOCALITY: u8, const WRITE: bool>(ptr: *const u8) {
arch::prefetch::<LOCALITY, WRITE>(ptr);
}
unsafe fn disable_denormals() -> Result<bool, crate::simd::UnsupportedError> {
unsafe { Ok(arch::disable_denormals()) }
}
#[allow(clippy::unit_arg)]
unsafe fn enable_denormals() -> Result<(), crate::simd::UnsupportedError> {
unsafe { Ok(arch::enable_denormals()) }
}
}
impl NativeSimd for X86V1 {
type f32xN = F32x4V1;
type i32xN = I32x4V1;
type u32xN = U32x4V1;
type f64xN = F64x2V1;
type i64xN = I64x2V1;
type u64xN = U64x2V1;
type i16xN = I16x8V1;
type u16xN = U16x8V1;
type i8xN = I8x16V1;
type u8xN = U8x16V1;
}
macro_rules! impl_indexable {
($idx:ty => $($ty:ty),* $(,)?) => {$( impl IndexableRegister<$idx> for $ty {} )*};
}
impl_indexable!(<X86V1 as Simd>::u32x2 => F64x2V1, I64x2V1, U64x2V1);
impl_indexable!(<X86V1 as Simd>::u64x2 => F64x2V1, I64x2V1, U64x2V1);
impl_indexable!(<X86V1 as Simd>::u32x4 => F32x4V1, I32x4V1, U32x4V1, <X86V1 as Simd>::u64x4, <X86V1 as Simd>::i64x4, <X86V1 as Simd>::f64x4);
impl_indexable!(<X86V1 as Simd>::u64x4 => F32x4V1, I32x4V1, U32x4V1);
impl Simd for X86V1 {
type usizex2 = <() as FindUSize<(), Self::u32x2, Self::u64x2>>::Output;
type usizex4 = <() as FindUSize<(), Self::u32x4, Self::u64x4>>::Output;
type usizex8 = <() as FindUSize<(), Self::u32x8, Self::u64x8>>::Output;
type usizex16 = <() as FindUSize<(), Self::u32x16, Self::u64x16>>::Output;
type f32x2 = half::F32x2V1;
type i32x2 = half::I32x2V1;
type u32x2 = half::U32x2V1;
type f32x4 = F32x4V1;
type i32x4 = I32x4V1;
type u32x4 = U32x4V1;
type f64x2 = F64x2V1;
type i64x2 = I64x2V1;
type u64x2 = U64x2V1;
type f32x8 = ArrayRegister<F32x4V1, 2>;
type i32x8 = ArrayRegister<I32x4V1, 2>;
type u32x8 = ArrayRegister<U32x4V1, 2>;
type f64x4 = ArrayRegister<F64x2V1, 2>;
type i64x4 = ArrayRegister<I64x2V1, 2>;
type u64x4 = ArrayRegister<U64x2V1, 2>;
type f64x8 = ArrayRegister<F64x2V1, 4>;
type i64x8 = ArrayRegister<I64x2V1, 4>;
type u64x8 = ArrayRegister<U64x2V1, 4>;
type f32x16 = ArrayRegister<F32x4V1, 4>;
type i32x16 = ArrayRegister<I32x4V1, 4>;
type u32x16 = ArrayRegister<U32x4V1, 4>;
type f64x16 = ArrayRegister<F64x2V1, 8>;
type i64x16 = ArrayRegister<I64x2V1, 8>;
type u64x16 = ArrayRegister<U64x2V1, 8>;
type i16x2 = ArrayRegister<i16, 2>;
type u16x2 = ArrayRegister<u16, 2>;
type i16x4 = half16::I16x4V1;
type u16x4 = half16::U16x4V1;
type i16x8 = I16x8V1;
type u16x8 = U16x8V1;
type i16x16 = ArrayRegister<I16x8V1, 2>;
type u16x16 = ArrayRegister<U16x8V1, 2>;
type i8x16 = I8x16V1;
type u8x16 = U8x16V1;
type i8x2 = ArrayRegister<i8, 2>;
type u8x2 = ArrayRegister<u8, 2>;
type i8x4 = half8::I8x4V1;
type u8x4 = half8::U8x4V1;
type i8x8 = half8::I8x8V1;
type u8x8 = half8::U8x8V1;
}
impl Simd3 for X86V1 {
type usizex3 = <Self as Simd3A>::usizex3A;
type f32x3 = <Self as Simd3A>::f32x3A;
type i32x3 = <Self as Simd3A>::i32x3A;
type u32x3 = <Self as Simd3A>::u32x3A;
type f64x3 = <Self as Simd3A>::f64x3A;
type i64x3 = <Self as Simd3A>::i64x3A;
type u64x3 = <Self as Simd3A>::u64x3A;
}
impl_packed_fp8!(
ArrayRegister<u8, 2> => half::F32x2V1,
half8::U8x4V1 => F32x4V1,
half8::U8x8V1 => ArrayRegister<F32x4V1, 2>,
U8x16V1 => ArrayRegister<F32x4V1, 4>,
);
impl_bit_casts_identity! {
U8x16V1 as U16x8V1,
U8x16V1 as U32x4V1,
U8x16V1 as U64x2V1,
}
impl_sad_native_u64!(U8x16V1 => (U16x8V1, U32x4V1, U64x2V1) via _mm_sad_epu8);
impl_sad_scalar! {
half8::U8x8V1 => (half16::U16x4V1, half::U32x2V1, u64),
half8::U8x4V1 => (ArrayRegister<u16, 2>, u32, u64),
}
impl_bit_casts_identity! {
U16x8V1 as U32x4V1,
U16x8V1 as U64x2V1,
U32x4V1 as U64x2V1,
}
impl_sad_u16!(@swar U16x8V1 => (U32x4V1, U64x2V1));
impl_sad_u32!(@swar U32x4V1 => U64x2V1);
impl_sad_u16!(@scalar half16::U16x4V1 => (half::U32x2V1, u64));
impl_sad_u32!(@scalar half::U32x2V1 => u64);
impl_indexable!(U16x8V1 => I16x8V1, U16x8V1);
impl_indexable!(<X86V1 as Simd>::u32x8 => I16x8V1, U16x8V1);
impl_indexable!(<X86V1 as Simd>::u64x8 => I16x8V1, U16x8V1);
impl_indexable!(<X86V1 as Simd>::u32x2 => ArrayRegister<i16, 2>, ArrayRegister<u16, 2>, ArrayRegister<i8, 2>, ArrayRegister<u8, 2>);
impl_indexable!(<X86V1 as Simd>::u64x2 => ArrayRegister<i16, 2>, ArrayRegister<u16, 2>, ArrayRegister<i8, 2>, ArrayRegister<u8, 2>);
impl_indexable!(<X86V1 as Simd>::u64x16 => ArrayRegister<I16x8V1, 2>, ArrayRegister<U16x8V1, 2>);
impl_indexable!(U8x16V1 => I8x16V1, U8x16V1);
impl_indexable!(<X86V1 as Simd>::u32x16 => I8x16V1, U8x16V1);
impl_indexable!(<X86V1 as Simd>::u64x16 => I8x16V1, U8x16V1);
impl_concat_bool_register2!(f32, half::F32x2V1);
impl_concat_bool_register2!(u32, half::U32x2V1);
impl_concat_bool_register2!(i32, half::I32x2V1);
impl_concat_bool_register2!(f64, F64x2V1);
impl_concat_bool_register2!(u64, U64x2V1);
impl_concat_bool_register2!(i64, I64x2V1);
impl_bit_casts! {
F64x2V1 as I64x2V1 => _mm_castpd_si128, F64x2V1 as U64x2V1 => _mm_castpd_si128, I64x2V1 as F64x2V1 => _mm_castsi128_pd, U64x2V1 as F64x2V1 => _mm_castsi128_pd,
F32x4V1 as I32x4V1 => _mm_castps_si128, F32x4V1 as U32x4V1 => _mm_castps_si128, I32x4V1 as F32x4V1 => _mm_castsi128_ps, U32x4V1 as F32x4V1 => _mm_castsi128_ps,
U32x4V1 as I32x4V1 => identity, I32x4V1 as U32x4V1 => identity, U64x2V1 as I64x2V1 => identity, I64x2V1 as U64x2V1 => identity,
U32x4V1 as U32x4V1 => identity, I32x4V1 as I32x4V1 => identity, I64x2V1 as I64x2V1 => identity, F32x4V1 as F32x4V1 => identity, F64x2V1 as F64x2V1 => identity, U64x2V1 as U64x2V1 => identity,
U16x8V1 as I16x8V1 => identity, I16x8V1 as U16x8V1 => identity,
I16x8V1 as I16x8V1 => identity, U16x8V1 as U16x8V1 => identity,
U8x16V1 as I8x16V1 => identity, I8x16V1 as U8x16V1 => identity,
I8x16V1 as I8x16V1 => identity, U8x16V1 as U8x16V1 => identity,
}
impl_type_casts! {
F32x4V1 as F32x4V1 => identity, F64x2V1 as F64x2V1 => identity, I32x4V1 as I32x4V1 => identity, I64x2V1 as I64x2V1 => identity, U32x4V1 as U32x4V1 => identity, U64x2V1 as U64x2V1 => identity,
I32x4V1 as F32x4V1 => _mm_cvtepi32_ps, U32x4V1 as F32x4V1 => _mm_cvtepu32_psx_v1, I64x2V1 as F64x2V1 => _mm_cvtepi64_pdx_v1 | _mm_cvtepi64_pdx_limited_v1, U64x2V1 as F64x2V1 => _mm_cvtepu64_pdx_v1 | _mm_cvtepu64_pdx_limited_v1,
I32x4V1 as U32x4V1 => identity, U32x4V1 as I32x4V1 => identity, I64x2V1 as U64x2V1 => identity, U64x2V1 as I64x2V1 => identity,
I16x8V1 as I16x8V1 => identity, U16x8V1 as U16x8V1 => identity,
I16x8V1 as U16x8V1 => identity, U16x8V1 as I16x8V1 => identity,
I8x16V1 as I8x16V1 => identity, U8x16V1 as U8x16V1 => identity,
I8x16V1 as U8x16V1 => identity, U8x16V1 as I8x16V1 => identity,
}
impl_float_to_int_casts! {
F32x4V1 as I32x4V1 => _mm_cvttps_epi32 sat _mm_cvtps_epi32_satx_v1, F32x4V1 as U32x4V1 => _mm_cvtps_epu32x_v1 sat _mm_cvtps_epu32_satx_v1, F64x2V1 as I64x2V1 => _mm_cvtpd_epi64x_v1 sat _mm_cvtpd_epi64_satx_v1 | _mm_cvtpd_epi64x_limited_v1, F64x2V1 as U64x2V1 => _mm_cvtpd_epu64x_v1 sat _mm_cvtpd_epu64_satx_v1 | _mm_cvtpd_epu64x_limited_v1, }
impl_cast_via! {
ArrayRegister<U64x2V1, 2> as F32x4V1 => via ArrayRegister<F64x2V1, 2>,
}
impl_float_cast_matrix! {
[half::F32x2V1, F64x2V1, half::I32x2V1, half::U32x2V1, I64x2V1, U64x2V1,
ArrayRegister<i16, 2>, ArrayRegister<u16, 2>, ArrayRegister<i8, 2>, ArrayRegister<u8, 2>],
[F32x4V1, ArrayRegister<F64x2V1, 2>, I32x4V1, U32x4V1, ArrayRegister<I64x2V1, 2>, ArrayRegister<U64x2V1, 2>,
half16::I16x4V1, half16::U16x4V1, half8::I8x4V1, half8::U8x4V1],
}
impl_sign_cast_matrix! {
[half::F32x2V1, F64x2V1, half::I32x2V1, half::U32x2V1, I64x2V1, U64x2V1,
ArrayRegister<i16, 2>, ArrayRegister<u16, 2>, ArrayRegister<i8, 2>, ArrayRegister<u8, 2>],
[F32x4V1, ArrayRegister<F64x2V1, 2>, I32x4V1, U32x4V1, ArrayRegister<I64x2V1, 2>, ArrayRegister<U64x2V1, 2>,
half16::I16x4V1, half16::U16x4V1, half8::I8x4V1, half8::U8x4V1],
}
impl_sign_cast_matrix_8_16_to_32_64! {
[ArrayRegister<I32x4V1, 2>, ArrayRegister<U32x4V1, 2>, ArrayRegister<I64x2V1, 4>, ArrayRegister<U64x2V1, 4>,
I16x8V1, U16x8V1, half8::I8x8V1, half8::U8x8V1],
}
impl_cast_from_via! {
ArrayRegister<I16x8V1, 2> as ArrayRegister<U64x2V1, 8> => via ArrayRegister<I64x2V1, 8>,
ArrayRegister<U16x8V1, 2> as ArrayRegister<I64x2V1, 8> => via ArrayRegister<U64x2V1, 8>,
ArrayRegister<I64x2V1, 8> as ArrayRegister<U16x8V1, 2> => via ArrayRegister<I16x8V1, 2>,
ArrayRegister<U64x2V1, 8> as ArrayRegister<I16x8V1, 2> => via ArrayRegister<U16x8V1, 2>,
}
impl_cast_from_via! {
I64x2V1 as half::F32x2V1 => via F64x2V1,
U64x2V1 as half::F32x2V1 => via F64x2V1,
ArrayRegister<I64x2V1, 2> as F32x4V1 => via ArrayRegister<F64x2V1, 2>,
}
#[thermite_macros::inline_always]
impl crate::register::CastRegister<I32x4V1> for ArrayRegister<F64x2V1, 2> {
fn cast_from(value: Storage<I32x4V1>) -> Storage<Self> {
ArrayRegister(unsafe { arch::_mm_cvtepi32_2pdx_v1(value) })
}
}
#[thermite_macros::inline_always]
impl crate::register::CastRegister<U32x4V1> for ArrayRegister<F64x2V1, 2> {
fn cast_from(value: Storage<U32x4V1>) -> Storage<Self> {
ArrayRegister(unsafe { arch::_mm_cvtepu32_2pdx_v1(value) })
}
}
impl_sign_cast_matrix_8_to_32_64! {
[ArrayRegister<I32x4V1, 4>, ArrayRegister<U32x4V1, 4>, ArrayRegister<I64x2V1, 8>, ArrayRegister<U64x2V1, 8>,
I8x16V1, U8x16V1],
}
impl_sign_cast_matrix_8_16! {
[half16::I16x4V1, half16::U16x4V1, half8::I8x4V1, half8::U8x4V1],
[I16x8V1, U16x8V1, half8::I8x8V1, half8::U8x8V1],
[ArrayRegister<I16x8V1, 2>, ArrayRegister<U16x8V1, 2>, I8x16V1, U8x16V1],
}
impl_cast_via! {
ArrayRegister<F32x4V1, 2> as I16x8V1 => via ArrayRegister<I32x4V1, 2>,
ArrayRegister<F32x4V1, 2> as half8::I8x8V1 => via ArrayRegister<I32x4V1, 2>,
ArrayRegister<F32x4V1, 2> as U16x8V1 => via ArrayRegister<U32x4V1, 2>,
ArrayRegister<F32x4V1, 2> as half8::U8x8V1 => via ArrayRegister<U32x4V1, 2>,
ArrayRegister<F64x2V1, 4> as I16x8V1 => via ArrayRegister<I64x2V1, 4>,
ArrayRegister<F64x2V1, 4> as half8::I8x8V1 => via ArrayRegister<I64x2V1, 4>,
ArrayRegister<F64x2V1, 4> as U16x8V1 => via ArrayRegister<U64x2V1, 4>,
ArrayRegister<F64x2V1, 4> as half8::U8x8V1 => via ArrayRegister<U64x2V1, 4>,
ArrayRegister<F32x4V1, 4> as I8x16V1 => via ArrayRegister<I32x4V1, 4>,
ArrayRegister<F32x4V1, 4> as U8x16V1 => via ArrayRegister<U32x4V1, 4>,
ArrayRegister<F64x2V1, 8> as ArrayRegister<I16x8V1, 2> => via ArrayRegister<I64x2V1, 8>,
ArrayRegister<F64x2V1, 8> as ArrayRegister<U16x8V1, 2> => via ArrayRegister<U64x2V1, 8>,
ArrayRegister<F64x2V1, 8> as I8x16V1 => via ArrayRegister<I64x2V1, 8>,
ArrayRegister<F64x2V1, 8> as U8x16V1 => via ArrayRegister<U64x2V1, 8>,
}
impl_mask_casts! {
I32x4V1 as I32x4V1 => identity, U32x4V1 as U32x4V1 => identity, I64x2V1 as I64x2V1 => identity, U64x2V1 as U64x2V1 => identity, F32x4V1 as F32x4V1 => identity, F64x2V1 as F64x2V1 => identity,
I32x4V1 as U32x4V1 => identity, U32x4V1 as I32x4V1 => identity, I64x2V1 as U64x2V1 => identity, U64x2V1 as I64x2V1 => identity,
I32x4V1 as F32x4V1 => _mm_castsi128_ps, U32x4V1 as F32x4V1 => _mm_castsi128_ps, I64x2V1 as F64x2V1 => _mm_castsi128_pd, U64x2V1 as F64x2V1 => _mm_castsi128_pd, F32x4V1 as I32x4V1 => _mm_castps_si128, F32x4V1 as U32x4V1 => _mm_castps_si128, F64x2V1 as I64x2V1 => _mm_castpd_si128, F64x2V1 as U64x2V1 => _mm_castpd_si128,
I16x8V1 as I16x8V1 => identity, U16x8V1 as U16x8V1 => identity,
I16x8V1 as U16x8V1 => identity, U16x8V1 as I16x8V1 => identity,
I8x16V1 as I8x16V1 => identity, U8x16V1 as U8x16V1 => identity,
I8x16V1 as U8x16V1 => identity, U8x16V1 as I8x16V1 => identity,
}
macro_rules! impl_extend_same {
($($ty:ty),* $(,)?) => {$( impl crate::register::ExtendRegister<$ty> for $ty {
#[inline(always)]
fn extend(value: Storage<$ty>) -> Storage<Self> {
value
}
#[inline(always)]
fn narrow(value: Storage<Self>) -> Storage<$ty> {
value
}
} )*};
}
impl_extend_same!(
F32x4V1, I32x4V1, U32x4V1, F64x2V1, I64x2V1, U64x2V1, I16x8V1, U16x8V1, I8x16V1, U8x16V1
);