1use self as ls;
4use crate::intrinsics::simd as is;
5
6pub(super) const trait SimdExt: Sized {
12 type Elem;
13
14 unsafe fn splat(v: i64) -> Self;
15}
16
17macro_rules! impl_simd_ext {
18 ($v:ident, $e:ty) => {
19 #[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
20 impl const SimdExt for crate::core_arch::simd::$v {
21 type Elem = $e;
22
23 #[inline(always)]
24 unsafe fn splat(v: i64) -> Self {
25 is::simd_splat(v as Self::Elem)
26 }
27 }
28 };
29}
30
31impl_simd_ext!(i8x16, i8);
32impl_simd_ext!(i8x32, i8);
33impl_simd_ext!(u8x16, u8);
34impl_simd_ext!(u8x32, u8);
35impl_simd_ext!(i16x8, i16);
36impl_simd_ext!(i16x16, i16);
37impl_simd_ext!(u16x8, u16);
38impl_simd_ext!(u16x16, u16);
39impl_simd_ext!(i32x4, i32);
40impl_simd_ext!(i32x8, i32);
41impl_simd_ext!(u32x4, u32);
42impl_simd_ext!(u32x8, u32);
43impl_simd_ext!(i64x2, i64);
44impl_simd_ext!(i64x4, i64);
45impl_simd_ext!(u64x2, u64);
46impl_simd_ext!(u64x4, u64);
47
48#[inline(always)]
49#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
50pub(crate) const unsafe fn simd_abs<T: Copy + const SimdExt>(a: T) -> T {
51 let m: T = is::simd_lt(a, ls::simd_splat(0));
52 is::simd_select(m, is::simd_neg(a), a)
53}
54
55#[inline(always)]
56#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
57pub(crate) const unsafe fn simd_absd<T: Copy>(a: T, b: T) -> T {
58 let m: T = is::simd_gt(a, b);
59 is::simd_select(m, is::simd_sub(a, b), is::simd_sub(b, a))
60}
61
62#[inline(always)]
63#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
64pub(crate) const unsafe fn simd_adda<T: Copy + const SimdExt>(a: T, b: T) -> T {
65 is::simd_add(ls::simd_abs(a), ls::simd_abs(b))
66}
67
68#[inline(always)]
69#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
70pub(super) const unsafe fn simd_andn<T: Copy + const SimdExt>(a: T, b: T) -> T {
71 is::simd_and(ls::simd_not(a), b)
72}
73
74#[inline(always)]
75#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
76pub(super) const unsafe fn simd_bitclr<T: Copy + const SimdExt>(a: T, b: T) -> T {
77 ls::simd_andn(ls::simd_shl(ls::simd_splat(1), b), a)
78}
79
80#[inline(always)]
81#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
82pub(super) const unsafe fn simd_bitrev<T: Copy + const SimdExt>(a: T, b: T) -> T {
83 is::simd_xor(ls::simd_shl(ls::simd_splat(1), b), a)
84}
85
86#[inline(always)]
87#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
88pub(super) const unsafe fn simd_bitset<T: Copy + const SimdExt>(a: T, b: T) -> T {
89 is::simd_or(ls::simd_shl(ls::simd_splat(1), b), a)
90}
91
92#[inline(always)]
93#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
94pub(super) const unsafe fn simd_fmsub<T: Copy>(a: T, b: T, c: T) -> T {
95 is::simd_fma(a, b, is::simd_neg(c))
96}
97
98#[inline(always)]
99#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
100pub(super) const unsafe fn simd_fnmadd<T: Copy>(a: T, b: T, c: T) -> T {
101 is::simd_neg(is::simd_fma(a, b, c))
102}
103
104#[inline(always)]
105#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
106pub(super) const unsafe fn simd_fnmsub<T: Copy>(a: T, b: T, c: T) -> T {
107 is::simd_neg(ls::simd_fmsub(a, b, c))
108}
109
110#[inline(always)]
111#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
112pub(super) const unsafe fn simd_madd<T: Copy>(a: T, b: T, c: T) -> T {
113 is::simd_add(a, is::simd_mul(b, c))
114}
115
116#[inline(always)]
117#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
118pub(super) const unsafe fn simd_msub<T: Copy>(a: T, b: T, c: T) -> T {
119 is::simd_sub(a, is::simd_mul(b, c))
120}
121
122#[inline(always)]
123#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
124pub(super) const unsafe fn simd_nor<T: Copy + const SimdExt>(a: T, b: T) -> T {
125 ls::simd_not(is::simd_or(a, b))
126}
127
128#[inline(always)]
129#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
130pub(super) const unsafe fn simd_not<T: Copy + const SimdExt>(a: T) -> T {
131 is::simd_xor(a, ls::simd_splat(!0))
132}
133
134#[inline(always)]
135#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
136pub(super) const unsafe fn simd_orn<T: Copy + const SimdExt>(a: T, b: T) -> T {
137 is::simd_or(a, ls::simd_not(b))
138}
139
140#[inline(always)]
141#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
142pub(super) const unsafe fn simd_shl<T: Copy + const SimdExt>(a: T, b: T) -> T {
143 let m = (size_of::<T::Elem>() * 8 - 1) as i64;
144 is::simd_shl(a, is::simd_and(b, ls::simd_splat(m)))
145}
146
147#[inline(always)]
148#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
149pub(super) const unsafe fn simd_shr<T: Copy + const SimdExt>(a: T, b: T) -> T {
150 let m = (size_of::<T::Elem>() * 8 - 1) as i64;
151 is::simd_shr(a, is::simd_and(b, ls::simd_splat(m)))
152}
153
154#[inline(always)]
155#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")]
156pub(super) const unsafe fn simd_splat<T: Copy + const SimdExt>(a: i64) -> T {
157 T::splat(a)
158}
159
160macro_rules! impl_vv {
161 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ty) => {
162 #[inline]
163 #[target_feature(enable = $ft)]
164 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
165 pub fn $name(a: $oty) -> $oty {
166 unsafe {
167 let a: $ity = transmute(a);
168 let r: $ity = $op(a);
169 transmute(r)
170 }
171 }
172 };
173}
174
175pub(super) use impl_vv;
176
177macro_rules! impl_gv {
178 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $gty:ty) => {
179 #[inline]
180 #[target_feature(enable = $ft)]
181 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
182 pub fn $name(a: $gty) -> $oty {
183 unsafe {
184 let r: $ity = $op(a.into());
185 transmute(r)
186 }
187 }
188 };
189}
190
191pub(super) use impl_gv;
192
193macro_rules! impl_sv {
194 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $ibs:expr) => {
195 #[inline]
196 #[target_feature(enable = $ft)]
197 #[rustc_legacy_const_generics(0)]
198 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
199 pub fn $name<const IMM: i32>() -> $oty {
200 static_assert_simm_bits!(IMM, $ibs);
201 unsafe {
202 let r: $ity = $op(IMM.into());
203 transmute(r)
204 }
205 }
206 };
207}
208
209pub(super) use impl_sv;
210
211macro_rules! impl_vvv {
212 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ty) => {
213 #[inline]
214 #[target_feature(enable = $ft)]
215 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
216 pub fn $name(a: $oty, b: $oty) -> $oty {
217 unsafe {
218 let a: $ity = transmute(a);
219 let b: $ity = transmute(b);
220 let r: $ity = $op(a, b);
221 transmute(r)
222 }
223 }
224 };
225}
226
227pub(super) use impl_vvv;
228
229macro_rules! impl_vuv {
230 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident) => {
231 #[inline]
232 #[target_feature(enable = $ft)]
233 #[rustc_legacy_const_generics(1)]
234 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
235 pub fn $name<const IMM: u32>(a: $oty) -> $oty {
236 static_assert_uimm_bits!(IMM, (size_of::<<$ity as SimdExt>::Elem>() * 8).ilog2());
237 unsafe {
238 let a: $ity = transmute(a);
239 let b: $ity = ls::simd_splat(IMM.into());
240 let r: $ity = $op(a, b);
241 transmute(r)
242 }
243 }
244 };
245 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $ibs:expr) => {
246 #[inline]
247 #[target_feature(enable = $ft)]
248 #[rustc_legacy_const_generics(1)]
249 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
250 pub fn $name<const IMM: u32>(a: $oty) -> $oty {
251 static_assert_uimm_bits!(IMM, $ibs);
252 unsafe {
253 let a: $ity = transmute(a);
254 let b: $ity = ls::simd_splat(IMM.into());
255 let r: $ity = $op(a, b);
256 transmute(r)
257 }
258 }
259 };
260}
261
262pub(super) use impl_vuv;
263
264macro_rules! impl_vug {
265 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $gty:ty, $ibs:expr) => {
266 #[inline]
267 #[target_feature(enable = $ft)]
268 #[rustc_legacy_const_generics(1)]
269 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
270 pub fn $name<const IMM: u32>(a: $oty) -> $gty {
271 static_assert_uimm_bits!(IMM, $ibs);
272 unsafe {
273 let a: $ity = transmute(a);
274 let r: <$ity as SimdExt>::Elem = $op(a, IMM);
275 r as $gty
276 }
277 }
278 };
279}
280
281pub(super) use impl_vug;
282
283macro_rules! impl_vsv {
284 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $ibs:expr) => {
285 #[inline]
286 #[target_feature(enable = $ft)]
287 #[rustc_legacy_const_generics(1)]
288 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
289 pub fn $name<const IMM: i32>(a: $oty) -> $oty {
290 static_assert_simm_bits!(IMM, $ibs);
291 unsafe {
292 let a: $ity = transmute(a);
293 let b: $ity = ls::simd_splat(IMM.into());
294 let r: $ity = $op(a, b);
295 transmute(r)
296 }
297 }
298 };
299}
300
301pub(super) use impl_vsv;
302
303macro_rules! impl_vvvv {
304 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ty) => {
305 #[inline]
306 #[target_feature(enable = $ft)]
307 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
308 pub fn $name(a: $oty, b: $oty, c: $oty) -> $oty {
309 unsafe {
310 let a: $ity = transmute(a);
311 let b: $ity = transmute(b);
312 let c: $ity = transmute(c);
313 let r: $ity = $op(a, b, c);
314 transmute(r)
315 }
316 }
317 };
318}
319
320pub(super) use impl_vvvv;
321
322macro_rules! impl_vugv {
323 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $gty:ty, $ibs:expr) => {
324 #[inline]
325 #[target_feature(enable = $ft)]
326 #[rustc_legacy_const_generics(1)]
327 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
328 pub fn $name<const IMM: u32>(a: $oty, b: $gty) -> $oty {
329 static_assert_uimm_bits!(IMM, $ibs);
330 unsafe {
331 let a: $ity = transmute(a);
332 let r: $ity = $op(a, IMM, b as <$ity as SimdExt>::Elem);
333 transmute(r)
334 }
335 }
336 };
337}
338
339pub(super) use impl_vugv;