From 5ebcf5669329a8adf515b12a5f506a16095c7f0d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 14 May 2023 19:35:25 +0000 Subject: [PATCH] Add vec_splat --- .../crates/core_arch/src/powerpc/altivec.rs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index 4c52dd8b7930..9c99f81afd23 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -1162,6 +1162,70 @@ mod sealed { impl_abss! { vec_abss_i16, i16x8 } impl_abss! { vec_abss_i32, i32x4 } + #[inline] + #[target_feature(enable = "altivec")] + #[cfg_attr(test, assert_instr(vspltb, IMM4 = 15))] + unsafe fn vspltb(a: vector_signed_char) -> vector_signed_char { + static_assert_uimm_bits!(IMM4, 4); + let b = u8x16::splat(IMM4 as u8); + vec_perm(a, a, transmute(b)) + } + + #[inline] + #[target_feature(enable = "altivec")] + #[cfg_attr(test, assert_instr(vsplth, IMM3 = 7))] + unsafe fn vsplth(a: vector_signed_short) -> vector_signed_short { + static_assert_uimm_bits!(IMM3, 3); + let b0 = IMM3 as u8 * 2; + let b1 = b0 + 1; + let b = u8x16::new( + b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, + ); + vec_perm(a, a, transmute(b)) + } + + #[inline] + #[target_feature(enable = "altivec")] + #[cfg_attr(all(test, not(target_feature = "vsx")), assert_instr(vspltw, IMM2 = 3))] + #[cfg_attr(all(test, target_feature = "vsx"), assert_instr(xxspltw, IMM2 = 3))] + unsafe fn vspltw(a: vector_signed_int) -> vector_signed_int { + static_assert_uimm_bits!(IMM2, 2); + let b0 = IMM2 as u8 * 4; + let b1 = b0 + 1; + let b2 = b0 + 2; + let b3 = b0 + 3; + let b = u8x16::new( + b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, b0, b1, b2, b3, + ); + vec_perm(a, a, transmute(b)) + } + + pub trait VectorSplat { + unsafe fn vec_splat(self) -> Self; + } + + macro_rules! impl_vec_splat { + ($ty:ty, $fun:ident) => { + impl VectorSplat for $ty { + #[inline] + #[target_feature(enable = "altivec")] + unsafe fn vec_splat(self) -> Self { + transmute($fun::(transmute(self))) + } + } + }; + } + + impl_vec_splat! { vector_signed_char, vspltb } + impl_vec_splat! { vector_unsigned_char, vspltb } + impl_vec_splat! { vector_bool_char, vspltb } + impl_vec_splat! { vector_signed_short, vsplth } + impl_vec_splat! { vector_unsigned_short, vsplth } + impl_vec_splat! { vector_bool_short, vsplth } + impl_vec_splat! { vector_signed_int, vspltw } + impl_vec_splat! { vector_unsigned_int, vspltw } + impl_vec_splat! { vector_bool_int, vspltw } + macro_rules! splat { ($name:ident, $v:ident, $r:ident [$instr:ident, $doc:literal]) => { #[doc = $doc] @@ -2606,6 +2670,16 @@ where a.vec_abss() } +/// Vector Splat +#[inline] +#[target_feature(enable = "altivec")] +pub unsafe fn vec_splat(a: T) -> T +where + T: sealed::VectorSplat, +{ + a.vec_splat::() +} + splat! { vec_splat_u8, u8, u8x16 [vspltisb, "Vector Splat to Unsigned Byte"] } splat! { vec_splat_i8, i8, i8x16 [vspltisb, "Vector Splat to Signed Byte"] } splat! { vec_splat_u16, u16, u16x8 [vspltish, "Vector Splat to Unsigned Halfword"] }