1#![allow(non_camel_case_types)]
10
11use crate::core_arch::powerpc::*;
12
13#[cfg(test)]
14use stdarch_test::assert_instr;
15
16use crate::mem::transmute;
17
18types! {
19 #![unstable(feature = "stdarch_powerpc", issue = "111145")]
20
21 pub struct vector_signed_long(2 x i64);
24 pub struct vector_unsigned_long(2 x u64);
26 pub struct vector_bool_long(2 x i64);
28 pub struct vector_double(2 x f64);
30 }
36
37#[allow(improper_ctypes)]
38extern "C" {
39 #[link_name = "llvm.ppc.altivec.vperm"]
40 fn vperm(
41 a: vector_signed_int,
42 b: vector_signed_int,
43 c: vector_unsigned_char,
44 ) -> vector_signed_int;
45}
46
47mod sealed {
48 use super::*;
49 use crate::core_arch::simd::*;
50
51 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
52 pub trait VectorPermDI {
53 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
54 unsafe fn vec_xxpermdi(self, b: Self, dm: u8) -> Self;
55 }
56
57 #[inline]
59 #[target_feature(enable = "vsx")]
60 #[cfg_attr(all(test, target_endian = "little"), assert_instr(xxmrgld, dm = 0x0))]
61 #[cfg_attr(all(test, target_endian = "big"), assert_instr(xxspltd, dm = 0x0))]
62 unsafe fn xxpermdi(a: vector_signed_long, b: vector_signed_long, dm: u8) -> vector_signed_long {
63 let a: i64x2 = transmute(a);
64 let b: i64x2 = transmute(b);
65 let r: i64x2 = match dm & 0b11 {
66 0 => simd_shuffle!(a, b, [0b00, 0b10]),
67 1 => simd_shuffle!(a, b, [0b01, 0b10]),
68 2 => simd_shuffle!(a, b, [0b00, 0b11]),
69 _ => simd_shuffle!(a, b, [0b01, 0b11]),
70 };
71 transmute(r)
72 }
73
74 macro_rules! vec_xxpermdi {
75 {$impl: ident} => {
76 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
77 impl VectorPermDI for $impl {
78 #[inline]
79 #[target_feature(enable = "vsx")]
80 unsafe fn vec_xxpermdi(self, b: Self, dm: u8) -> Self {
81 transmute(xxpermdi(transmute(self), transmute(b), dm))
82 }
83 }
84 }
85 }
86
87 vec_xxpermdi! { vector_unsigned_long }
88 vec_xxpermdi! { vector_signed_long }
89 vec_xxpermdi! { vector_bool_long }
90 vec_xxpermdi! { vector_double }
91
92 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
93 pub trait VectorMergeEo {
94 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
95 unsafe fn vec_mergee(self, b: Self) -> Self;
96 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
97 unsafe fn vec_mergeo(self, b: Self) -> Self;
98 }
99
100 #[inline]
101 #[target_feature(enable = "altivec")]
102 #[cfg_attr(
103 all(test, target_endian = "little", target_feature = "power8-vector"),
104 assert_instr(vmrgow)
105 )]
106 #[cfg_attr(
107 all(test, target_endian = "big", target_feature = "power8-vector"),
108 assert_instr(vmrgew)
109 )]
110 unsafe fn mergee(a: vector_signed_int, b: vector_signed_int) -> vector_signed_int {
111 let p = transmute(u8x16::new(
112 0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19,
113 0x1A, 0x1B,
114 ));
115 vec_perm(a, b, p)
116 }
117
118 #[inline]
119 #[target_feature(enable = "altivec")]
120 #[cfg_attr(
121 all(test, target_endian = "little", target_feature = "power8-vector"),
122 assert_instr(vmrgew)
123 )]
124 #[cfg_attr(
125 all(test, target_endian = "big", target_feature = "power8-vector"),
126 assert_instr(vmrgow)
127 )]
128 unsafe fn mergeo(a: vector_signed_int, b: vector_signed_int) -> vector_signed_int {
129 let p = transmute(u8x16::new(
130 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17, 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D,
131 0x1E, 0x1F,
132 ));
133 vec_perm(a, b, p)
134 }
135
136 macro_rules! vec_mergeeo {
137 { $impl: ident, $even: ident, $odd: ident } => {
138 #[unstable(feature = "stdarch_powerpc", issue = "111145")]
139 impl VectorMergeEo for $impl {
140 #[inline]
141 #[target_feature(enable = "altivec")]
142 unsafe fn vec_mergee(self, b: Self) -> Self {
143 transmute(mergee(transmute(self), transmute(b)))
144 }
145 #[inline]
146 #[target_feature(enable = "altivec")]
147 unsafe fn vec_mergeo(self, b: Self) -> Self {
148 transmute(mergeo(transmute(self), transmute(b)))
149 }
150 }
151 }
152 }
153
154 vec_mergeeo! { vector_signed_int, mergee, mergeo }
155 vec_mergeeo! { vector_unsigned_int, mergee, mergeo }
156 vec_mergeeo! { vector_bool_int, mergee, mergeo }
157 vec_mergeeo! { vector_float, mergee, mergeo }
158}
159
160#[inline]
162#[target_feature(enable = "vsx")]
163#[unstable(feature = "stdarch_powerpc", issue = "111145")]
165pub unsafe fn vec_xxpermdi<T, const DM: i32>(a: T, b: T) -> T
166where
167 T: sealed::VectorPermDI,
168{
169 static_assert_uimm_bits!(DM, 2);
170 a.vec_xxpermdi(b, DM as u8)
171}
172
173#[inline]
182#[target_feature(enable = "altivec")]
183#[unstable(feature = "stdarch_powerpc", issue = "111145")]
184pub unsafe fn vec_mergee<T>(a: T, b: T) -> T
185where
186 T: sealed::VectorMergeEo,
187{
188 a.vec_mergee(b)
189}
190
191#[inline]
200#[target_feature(enable = "altivec")]
201#[unstable(feature = "stdarch_powerpc", issue = "111145")]
202pub unsafe fn vec_mergeo<T>(a: T, b: T) -> T
203where
204 T: sealed::VectorMergeEo,
205{
206 a.vec_mergeo(b)
207}
208
209#[cfg(test)]
210mod tests {
211 #[cfg(target_arch = "powerpc")]
212 use crate::core_arch::arch::powerpc::*;
213
214 #[cfg(target_arch = "powerpc64")]
215 use crate::core_arch::arch::powerpc64::*;
216
217 use crate::core_arch::simd::*;
218 use crate::mem::transmute;
219 use stdarch_test::simd_test;
220
221 macro_rules! test_vec_xxpermdi {
222 {$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => {
223 #[simd_test(enable = "vsx")]
224 unsafe fn $name() {
225 let a: $longtype = transmute($shorttype::new($($a),+, $($b),+));
226 let b = transmute($shorttype::new($($c),+, $($d),+));
227
228 assert_eq!($shorttype::new($($a),+, $($c),+), transmute(vec_xxpermdi::<_, 0>(a, b)));
229 assert_eq!($shorttype::new($($b),+, $($c),+), transmute(vec_xxpermdi::<_, 1>(a, b)));
230 assert_eq!($shorttype::new($($a),+, $($d),+), transmute(vec_xxpermdi::<_, 2>(a, b)));
231 assert_eq!($shorttype::new($($b),+, $($d),+), transmute(vec_xxpermdi::<_, 3>(a, b)));
232 }
233 }
234 }
235
236 test_vec_xxpermdi! {test_vec_xxpermdi_u64x2, u64x2, vector_unsigned_long, [0], [1], [2], [3]}
237 test_vec_xxpermdi! {test_vec_xxpermdi_i64x2, i64x2, vector_signed_long, [0], [-1], [2], [-3]}
238 test_vec_xxpermdi! {test_vec_xxpermdi_m64x2, m64x2, vector_bool_long, [false], [true], [false], [true]}
239 test_vec_xxpermdi! {test_vec_xxpermdi_f64x2, f64x2, vector_double, [0.0], [1.0], [2.0], [3.0]}
240}