1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#![allow(non_camel_case_types)]
use crate::core_arch::simd_llvm::*;
#[cfg(test)]
use stdarch_test::assert_instr;
use crate::mem;
types! {
pub struct vector_signed_long(i64, i64);
pub struct vector_unsigned_long(u64, u64);
pub struct vector_bool_long(i64, i64);
pub struct vector_double(f64, f64);
}
mod sealed {
use super::*;
use crate::core_arch::simd::*;
pub trait VectorPermDI {
unsafe fn vec_xxpermdi(self, b: Self, dm: u8) -> Self;
}
#[inline]
#[target_feature(enable = "vsx")]
#[cfg_attr(all(test, target_endian = "little"), assert_instr(xxmrgld, dm = 0x0))]
#[cfg_attr(all(test, target_endian = "big"), assert_instr(xxspltd, dm = 0x0))]
unsafe fn xxpermdi(a: i64x2, b: i64x2, dm: u8) -> i64x2 {
match dm & 0b11 {
0 => simd_shuffle2!(a, b, [0b00, 0b10]),
1 => simd_shuffle2!(a, b, [0b01, 0b10]),
2 => simd_shuffle2!(a, b, [0b00, 0b11]),
_ => simd_shuffle2!(a, b, [0b01, 0b11]),
}
}
macro_rules! vec_xxpermdi {
{$impl: ident} => {
impl VectorPermDI for $impl {
#[inline]
#[target_feature(enable = "vsx")]
unsafe fn vec_xxpermdi(self, b: Self, dm: u8) -> Self {
mem::transmute(xxpermdi(mem::transmute(self), mem::transmute(b), dm))
}
}
}
}
vec_xxpermdi! { vector_unsigned_long }
vec_xxpermdi! { vector_signed_long }
vec_xxpermdi! { vector_bool_long }
vec_xxpermdi! { vector_double }
}
#[inline]
#[target_feature(enable = "vsx")]
pub unsafe fn vec_xxpermdi<T, const DM: i32>(a: T, b: T) -> T
where
T: sealed::VectorPermDI,
{
static_assert_imm2!(DM);
a.vec_xxpermdi(b, DM as u8)
}
#[cfg(test)]
mod tests {
#[cfg(target_arch = "powerpc")]
use crate::core_arch::arch::powerpc::*;
#[cfg(target_arch = "powerpc64")]
use crate::core_arch::arch::powerpc64::*;
use super::mem;
use crate::core_arch::simd::*;
use stdarch_test::simd_test;
macro_rules! test_vec_xxpermdi {
{$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => {
#[simd_test(enable = "vsx")]
unsafe fn $name() {
let a: $longtype = mem::transmute($shorttype::new($($a),+, $($b),+));
let b = mem::transmute($shorttype::new($($c),+, $($d),+));
assert_eq!($shorttype::new($($a),+, $($c),+), mem::transmute(vec_xxpermdi::<_, 0>(a, b)));
assert_eq!($shorttype::new($($b),+, $($c),+), mem::transmute(vec_xxpermdi::<_, 1>(a, b)));
assert_eq!($shorttype::new($($a),+, $($d),+), mem::transmute(vec_xxpermdi::<_, 2>(a, b)));
assert_eq!($shorttype::new($($b),+, $($d),+), mem::transmute(vec_xxpermdi::<_, 3>(a, b)));
}
}
}
test_vec_xxpermdi! {test_vec_xxpermdi_u64x2, u64x2, vector_unsigned_long, [0], [1], [2], [3]}
test_vec_xxpermdi! {test_vec_xxpermdi_i64x2, i64x2, vector_signed_long, [0], [-1], [2], [-3]}
test_vec_xxpermdi! {test_vec_xxpermdi_m64x2, m64x2, vector_bool_long, [false], [true], [false], [true]}
test_vec_xxpermdi! {test_vec_xxpermdi_f64x2, f64x2, vector_double, [0.0], [1.0], [2.0], [3.0]}
}