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}
262
263pub(super) use impl_vuv;
264
265macro_rules! impl_vug {
266 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $gty:ty, $ibs:expr) => {
267 #[inline]
268 #[target_feature(enable = $ft)]
269 #[rustc_legacy_const_generics(1)]
270 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
271 pub fn $name<const IMM: u32>(a: $oty) -> $gty {
272 static_assert_uimm_bits!(IMM, $ibs);
273 unsafe {
274 let a: $ity = transmute(a);
275 let r: <$ity as SimdExt>::Elem = $op(a, IMM);
276 r as $gty
277 }
278 }
279 };
280}
281
282pub(super) use impl_vug;
283
284macro_rules! impl_vsv {
285 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $ibs:expr) => {
286 #[inline]
287 #[target_feature(enable = $ft)]
288 #[rustc_legacy_const_generics(1)]
289 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
290 pub fn $name<const IMM: i32>(a: $oty) -> $oty {
291 static_assert_simm_bits!(IMM, $ibs);
292 unsafe {
293 let a: $ity = transmute(a);
294 let b: $ity = ls::simd_splat(IMM.into());
295 let r: $ity = $op(a, b);
296 transmute(r)
297 }
298 }
299 };
300}
301
302pub(super) use impl_vsv;
303
304macro_rules! impl_vvvv {
305 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ty) => {
306 #[inline]
307 #[target_feature(enable = $ft)]
308 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
309 pub fn $name(a: $oty, b: $oty, c: $oty) -> $oty {
310 unsafe {
311 let a: $ity = transmute(a);
312 let b: $ity = transmute(b);
313 let c: $ity = transmute(c);
314 let r: $ity = $op(a, b, c);
315 transmute(r)
316 }
317 }
318 };
319}
320
321pub(super) use impl_vvvv;
322
323macro_rules! impl_vugv {
324 ($ft:literal, $name:ident, $op:path, $oty:ty, $ity:ident, $gty:ty, $ibs:expr) => {
325 #[inline]
326 #[target_feature(enable = $ft)]
327 #[rustc_legacy_const_generics(1)]
328 #[unstable(feature = "stdarch_loongarch", issue = "117427")]
329 pub fn $name<const IMM: u32>(a: $oty, b: $gty) -> $oty {
330 static_assert_uimm_bits!(IMM, $ibs);
331 unsafe {
332 let a: $ity = transmute(a);
333 let r: $ity = $op(a, IMM, b as <$ity as SimdExt>::Elem);
334 transmute(r)
335 }
336 }
337 };
338}
339
340pub(super) use impl_vugv;