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