Skip to content

Commit cf3363d

Browse files
committed
powerpc/vsx: implement vec_xl for vector_double
1 parent 474b389 commit cf3363d

3 files changed

Lines changed: 106 additions & 43 deletions

File tree

crates/core_arch/src/powerpc/altivec.rs

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -728,40 +728,8 @@ pub(crate) mod sealed {
728728
unsafe fn vec_xl(self, a: isize) -> Self::Result;
729729
}
730730

731-
macro_rules! impl_vec_xl {
732-
($fun:ident $notpwr9:ident / $pwr9:ident $ty:ident) => {
733-
#[inline]
734-
#[target_feature(enable = "altivec")]
735-
#[cfg_attr(
736-
all(test, not(target_feature = "power9-altivec")),
737-
assert_instr($notpwr9)
738-
)]
739-
#[cfg_attr(all(test, target_feature = "power9-altivec"), assert_instr($pwr9))]
740-
pub unsafe fn $fun(a: isize, b: *const $ty) -> t_t_l!($ty) {
741-
let addr = (b as *const u8).offset(a);
742-
743-
let mut r = mem::MaybeUninit::uninit();
744-
745-
crate::ptr::copy_nonoverlapping(
746-
addr,
747-
r.as_mut_ptr() as *mut u8,
748-
mem::size_of::<t_t_l!($ty)>(),
749-
);
750-
751-
r.assume_init()
752-
}
753-
754-
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
755-
impl VectorXl for *const $ty {
756-
type Result = t_t_l!($ty);
757-
#[inline]
758-
#[target_feature(enable = "altivec")]
759-
unsafe fn vec_xl(self, a: isize) -> Self::Result {
760-
$fun(a, self)
761-
}
762-
}
763-
};
764-
}
731+
// Use the impl_vec_xl macro from macros module
732+
use crate::core_arch::powerpc::macros::impl_vec_xl;
765733

766734
impl_vec_xl! { vec_xl_i8 lxvd2x / lxv i8 }
767735
impl_vec_xl! { vec_xl_u8 lxvd2x / lxv u8 }

crates/core_arch/src/powerpc/macros.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ macro_rules! t_t_l {
180180
(f32) => {
181181
vector_float
182182
};
183+
(f64) => {
184+
vector_double
185+
};
183186
}
184187

185188
macro_rules! t_t_s {
@@ -292,8 +295,45 @@ macro_rules! impl_vec_sld {
292295
)+ };
293296
}
294297

298+
macro_rules! impl_vec_xl {
299+
($fun:ident $notpwr9:ident / $pwr9:ident $ty:ident) => {
300+
#[inline]
301+
#[target_feature(enable = "vsx")]
302+
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
303+
#[cfg_attr(
304+
all(test, not(target_feature = "power9-altivec")),
305+
assert_instr($notpwr9)
306+
)]
307+
#[cfg_attr(all(test, target_feature = "power9-altivec"), assert_instr($pwr9))]
308+
pub unsafe fn $fun(a: isize, b: *const $ty) -> t_t_l!($ty) {
309+
let addr = (b as *const u8).offset(a);
310+
311+
let mut r = mem::MaybeUninit::uninit();
312+
313+
crate::ptr::copy_nonoverlapping(
314+
addr,
315+
r.as_mut_ptr() as *mut u8,
316+
mem::size_of::<t_t_l!($ty)>(),
317+
);
318+
319+
r.assume_init()
320+
}
321+
322+
#[unstable(feature = "stdarch_powerpc", issue = "111145")]
323+
impl VectorXl for *const $ty {
324+
type Result = t_t_l!($ty);
325+
#[inline]
326+
#[target_feature(enable = "vsx")]
327+
unsafe fn vec_xl(self, a: isize) -> Self::Result {
328+
$fun(a, self)
329+
}
330+
}
331+
};
332+
}
333+
295334
pub(crate) use impl_vec_sld;
296335
pub(crate) use impl_vec_trait;
336+
pub(crate) use impl_vec_xl;
297337
pub(crate) use s_t_l;
298338
pub(crate) use t_b;
299339
pub(crate) use t_t_l;

crates/core_arch/src/powerpc/vsx.rs

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
99
#![allow(non_camel_case_types)]
1010

11+
use super::macros::*;
1112
use crate::core_arch::powerpc::*;
1213
use crate::core_arch::simd::*;
13-
use super::macros::*;
1414

1515
#[cfg(test)]
1616
use stdarch_test::assert_instr;
1717

18-
use crate::mem::transmute;
18+
use crate::mem::{self, transmute};
1919

2020
types! {
2121
#![unstable(feature = "stdarch_powerpc", issue = "111145")]
@@ -172,11 +172,15 @@ mod sealed {
172172
vec_mergeeo! { vector_unsigned_int, mergee, mergeo }
173173
vec_mergeeo! { vector_bool_int, mergee, mergeo }
174174
vec_mergeeo! { vector_float, mergee, mergeo }
175-
}
176175

177-
// Implement AltiVec's VectorSld trait for vector_double to enable vec_sld support
178-
use crate::core_arch::powerpc::altivec::sealed::{VectorSld, vsldoi, xxsldwi};
179-
impl_vec_sld! { vector_double }
176+
// Implement vec_xl for f64 (vector_double).
177+
use crate::core_arch::powerpc::altivec::sealed::VectorXl;
178+
impl_vec_xl! { vec_xl_f64 lxvd2x / lxv f64 }
179+
180+
// Implement vec_sld for vector_double.
181+
use crate::core_arch::powerpc::altivec::sealed::{VectorSld, vsldoi, xxsldwi};
182+
impl_vec_sld! { vector_double }
183+
}
180184

181185
/// Vector permute.
182186
#[inline]
@@ -268,9 +272,9 @@ mod tests {
268272
let a = vector_double::from(f64x2::from_array([1.0, 2.0]));
269273
let b = vector_double::from(f64x2::from_array([3.0, 4.0]));
270274

271-
// Shift left by 8 bytes (1 f64 element)
272-
// On little-endian: shifts right in memory, result is [b[1], a[0]] = [4.0, 1.0]
273-
// On big-endian: shifts left in memory, result is [a[1], b[0]] = [2.0, 3.0]
275+
// Shift left by 8 bytes (1 f64 element).
276+
// On little-endian: shifts right in memory, result is [b[1], a[0]] = [4.0, 1.0].
277+
// On big-endian: shifts left in memory, result is [a[1], b[0]] = [2.0, 3.0].
274278
unsafe {
275279
let result: f64x2 = transmute(a.vec_sld::<8>(b));
276280
#[cfg(target_endian = "little")]
@@ -280,4 +284,55 @@ mod tests {
280284
assert_eq!(result, expected);
281285
}
282286
}
287+
288+
#[simd_test(enable = "vsx")]
289+
fn test_vec_sldw_f64x2() {
290+
use crate::core_arch::powerpc::altivec::sealed::VectorSld;
291+
292+
let a = vector_double::from(f64x2::from_array([1.0, 2.0]));
293+
let b = vector_double::from(f64x2::from_array([3.0, 4.0]));
294+
295+
// Shift left by 1 word (4 bytes).
296+
// vec_sldw shifts by words (4-byte units), so UIMM2=1 means shift by 4 bytes
297+
// whic is equivalent to vec_sld with UIMM4=4.
298+
unsafe {
299+
let result: f64x2 = transmute(a.vec_sldw::<1>(b));
300+
// Shifting by 4 bytes (half of an f64) will mix the high/low parts.
301+
// On little-endian: shifts right in memory, result is [b[1], a[0]] but with 4-byte shift.
302+
// On big-endian: shifts left in memory, result is [a[1], b[0]] but with 4-byte shift.
303+
// Since we're shifting by 4 bytes (half an f64), the result will have mixed bits.
304+
// Verify using vec_sld with the same shift amount for comparison.
305+
let expected: f64x2 = transmute(a.vec_sld::<4>(b));
306+
assert_eq!(result, expected);
307+
}
308+
}
309+
310+
#[simd_test(enable = "vsx")]
311+
fn test_vec_xl_f64() {
312+
let pat = [1.0f64, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
313+
314+
// Test loading from aligned offset 0
315+
unsafe {
316+
let result = vec_xl(0, pat.as_ptr());
317+
let result_f64: f64x2 = transmute(result);
318+
assert_eq!(result_f64.as_array()[0], 1.0);
319+
assert_eq!(result_f64.as_array()[1], 2.0);
320+
}
321+
322+
// Test loading from offset 16 (2 f64 elements = 16 bytes)
323+
unsafe {
324+
let result = vec_xl(16, pat.as_ptr());
325+
let result_f64: f64x2 = transmute(result);
326+
assert_eq!(result_f64.as_array()[0], 3.0);
327+
assert_eq!(result_f64.as_array()[1], 4.0);
328+
}
329+
330+
// Test loading from offset 32 (4 f64 elements = 32 bytes)
331+
unsafe {
332+
let result = vec_xl(32, pat.as_ptr());
333+
let result_f64: f64x2 = transmute(result);
334+
assert_eq!(result_f64.as_array()[0], 5.0);
335+
assert_eq!(result_f64.as_array()[1], 6.0);
336+
}
337+
}
283338
}

0 commit comments

Comments
 (0)