summaryrefslogtreecommitdiffstats
path: root/library/stdarch/crates/core_arch/src/powerpc/altivec.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/stdarch/crates/core_arch/src/powerpc/altivec.rs')
-rw-r--r--library/stdarch/crates/core_arch/src/powerpc/altivec.rs107
1 files changed, 106 insertions, 1 deletions
diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs
index ae10377ce..e94afa77d 100644
--- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs
+++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs
@@ -15,6 +15,7 @@
use crate::{
core_arch::{simd::*, simd_llvm::*},
+ mem,
mem::transmute,
};
@@ -318,6 +319,12 @@ extern "C" {
fn vupkhsh(a: vector_signed_short) -> vector_signed_int;
#[link_name = "llvm.ppc.altivec.vupklsh"]
fn vupklsh(a: vector_signed_short) -> vector_signed_int;
+
+ #[link_name = "llvm.ppc.altivec.mfvscr"]
+ fn mfvscr() -> vector_unsigned_short;
+
+ #[link_name = "llvm.ppc.altivec.vlogefp"]
+ fn vlogefp(a: vector_float) -> vector_float;
}
macro_rules! s_t_l {
@@ -528,6 +535,60 @@ mod sealed {
impl_vec_lde! { vec_lde_f32 lvewx f32 }
+ pub trait VectorXl {
+ type Result;
+ unsafe fn vec_xl(self, a: isize) -> Self::Result;
+ }
+
+ macro_rules! impl_vec_xl {
+ ($fun:ident $notpwr9:ident / $pwr9:ident $ty:ident) => {
+ #[inline]
+ #[target_feature(enable = "altivec")]
+ #[cfg_attr(
+ all(test, not(target_feature = "power9-altivec")),
+ assert_instr($notpwr9)
+ )]
+ #[cfg_attr(all(test, target_feature = "power9-altivec"), assert_instr($pwr9))]
+ pub unsafe fn $fun(a: isize, b: *const $ty) -> t_t_l!($ty) {
+ let addr = (b as *const u8).offset(a);
+
+ // Workaround ptr::copy_nonoverlapping not being inlined
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
+ #[rustc_nounwind]
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ }
+
+ let mut r = mem::MaybeUninit::uninit();
+
+ copy_nonoverlapping(
+ addr,
+ r.as_mut_ptr() as *mut u8,
+ mem::size_of::<t_t_l!($ty)>(),
+ );
+
+ r.assume_init()
+ }
+
+ impl VectorXl for *const $ty {
+ type Result = t_t_l!($ty);
+ #[inline]
+ #[target_feature(enable = "altivec")]
+ unsafe fn vec_xl(self, a: isize) -> Self::Result {
+ $fun(a, self)
+ }
+ }
+ };
+ }
+
+ impl_vec_xl! { vec_xl_i8 lxvd2x / lxv i8 }
+ impl_vec_xl! { vec_xl_u8 lxvd2x / lxv u8 }
+ impl_vec_xl! { vec_xl_i16 lxvd2x / lxv i16 }
+ impl_vec_xl! { vec_xl_u16 lxvd2x / lxv u16 }
+ impl_vec_xl! { vec_xl_i32 lxvd2x / lxv i32 }
+ impl_vec_xl! { vec_xl_u32 lxvd2x / lxv u32 }
+ impl_vec_xl! { vec_xl_f32 lxvd2x / lxv f32 }
+
test_impl! { vec_floor(a: vector_float) -> vector_float [ vfloor, vrfim / xvrspim ] }
test_impl! { vec_vexptefp(a: vector_float) -> vector_float [ vexptefp, vexptefp ] }
@@ -2501,6 +2562,24 @@ where
p.vec_lde(off)
}
+/// VSX Unaligned Load
+#[inline]
+#[target_feature(enable = "altivec")]
+pub unsafe fn vec_xl<T>(off: isize, p: T) -> <T as sealed::VectorXl>::Result
+where
+ T: sealed::VectorXl,
+{
+ p.vec_xl(off)
+}
+
+/// Vector Base-2 Logarithm Estimate
+#[inline]
+#[target_feature(enable = "altivec")]
+#[cfg_attr(test, assert_instr(vlogefp))]
+pub unsafe fn vec_loge(a: vector_float) -> vector_float {
+ vlogefp(a)
+}
+
/// Vector floor.
#[inline]
#[target_feature(enable = "altivec")]
@@ -2566,7 +2645,7 @@ pub unsafe fn vec_cmpb(a: vector_float, b: vector_float) -> vector_signed_int {
sealed::vec_vcmpbfp(a, b)
}
-/// Vector cmpb.
+/// Vector ceil.
#[inline]
#[target_feature(enable = "altivec")]
pub unsafe fn vec_ceil(a: vector_float) -> vector_float {
@@ -2737,6 +2816,14 @@ where
a.vec_max(b)
}
+/// Move From Vector Status and Control Register.
+#[inline]
+#[target_feature(enable = "altivec")]
+#[cfg_attr(test, assert_instr(mfvscr))]
+pub unsafe fn vec_mfvscr() -> vector_unsigned_short {
+ mfvscr()
+}
+
/// Vector add.
#[inline]
#[target_feature(enable = "altivec")]
@@ -3281,6 +3368,24 @@ mod tests {
}
#[simd_test(enable = "altivec")]
+ unsafe fn test_vec_xl() {
+ let pat = [
+ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
+ u8x16::new(
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ ),
+ ];
+
+ for off in 0..16 {
+ let val: u8x16 = transmute(vec_xl(0, (pat.as_ptr() as *const u8).offset(off)));
+ for i in 0..16 {
+ let v = val.extract(i);
+ assert_eq!(off as usize + i, v as usize);
+ }
+ }
+ }
+
+ #[simd_test(enable = "altivec")]
unsafe fn test_vec_ldl() {
let pat = [
u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),