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