native 0.0.1
Vectors, masks and wide register packs for C++26
Loading...
Searching...
No Matches
native.arm.rdm.ccm
1// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
2// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
3module;
4#include "native/isa_import.h"
5#include "native/arm/detail/integer_constant.h"
6#include "native/arm/rdm.h"
7#include "native/targets.h"
8export module native.arm.rdm;
9export import native.arm.features;
10export import native.simd;
11export {
12#if NATIVE_HOST_NEON || defined(NATIVE_DOXYGEN)
13namespace native {
26 // All vector operands share Arch; native registers remain implementation details.
28 template<isa<arm> Arch=NATIVE_BASELINE> requires(Arch.has(arm_feature::rdm))
29 native_nodiscard native_inline __attribute__((target("rdm")))
30 constexpr int16_t sqrdmlah(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
31 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
32 else {
33 auto result = detail::sqrdmlah<Arch>(
34 accumulator,
35 lhs,
36 rhs);
37 return result;
38 }
39 }
40
42 template<isa<arm> Arch=NATIVE_BASELINE> requires(!Arch.has(arm_feature::rdm))
43 native_nodiscard consteval int16_t sqrdmlah(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
44 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
45 }
46
48 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
49 native_nodiscard native_inline __attribute__((target("rdm")))
50 constexpr int16_t sqrdmlah_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 4, Arch> rhs) noexcept {
51 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
52 else {
53 auto result = detail::sqrdmlah_lane<Arch, Lane>(
54 accumulator,
55 lhs,
56 __builtin_bit_cast(int16x4_t, rhs.to_native()));
57 return result;
58 }
59 }
60
62 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 4, Arch>); })
63 native_nodiscard consteval int16_t sqrdmlah_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 4, Arch> rhs) noexcept {
64 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
65 }
66
68 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
69 native_nodiscard native_inline __attribute__((target("rdm")))
70 constexpr int16_t sqrdmlah_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 8, Arch> rhs) noexcept {
71 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
72 else {
73 auto result = detail::sqrdmlah_lane<Arch, Lane>(
74 accumulator,
75 lhs,
76 __builtin_bit_cast(int16x8_t, rhs.to_native()));
77 return result;
78 }
79 }
80
82 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 8, Arch>); })
83 native_nodiscard consteval int16_t sqrdmlah_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 8, Arch> rhs) noexcept {
84 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
85 }
86
88 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
89 native_nodiscard native_inline __attribute__((target("rdm")))
90 constexpr simd<std::int16_t, 4, Arch> sqrdmlah(
91 simd<std::int16_t, 4, Arch> accumulator,
92 simd<std::int16_t, 4, Arch> lhs,
93 simd<std::int16_t, 4, Arch> rhs) noexcept {
94 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
95 else {
96 auto result = detail::sqrdmlah<Arch>(
97 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
98 __builtin_bit_cast(int16x4_t, lhs.to_native()),
99 __builtin_bit_cast(int16x4_t, rhs.to_native()));
101 }
102 }
103
105 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int16_t, 4, Arch>); })
107 simd<std::int16_t, 4, Arch> accumulator,
109 simd<std::int16_t, 4, Arch> rhs) noexcept {
110 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
111 }
112
114 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
115 native_nodiscard native_inline __attribute__((target("rdm")))
116 constexpr simd<std::int16_t, 4, Arch> sqrdmlah_lane(
117 simd<std::int16_t, 4, Arch> accumulator,
118 simd<std::int16_t, 4, Arch> lhs,
119 simd<std::int16_t, 4, Arch> rhs) noexcept {
120 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
121 else {
122 auto result = detail::sqrdmlah_lane<Arch, Lane>(
123 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
124 __builtin_bit_cast(int16x4_t, lhs.to_native()),
125 __builtin_bit_cast(int16x4_t, rhs.to_native()));
127 }
128 }
129
131 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 4, Arch>); })
133 simd<std::int16_t, 4, Arch> accumulator,
135 simd<std::int16_t, 4, Arch> rhs) noexcept {
136 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
137 }
138
140 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
141 native_nodiscard native_inline __attribute__((target("rdm")))
142 constexpr simd<std::int16_t, 4, Arch> sqrdmlah_lane(
143 simd<std::int16_t, 4, Arch> accumulator,
144 simd<std::int16_t, 4, Arch> lhs,
145 simd<std::int16_t, 8, Arch> rhs) noexcept {
146 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
147 else {
148 auto result = detail::sqrdmlah_lane<Arch, Lane>(
149 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
150 __builtin_bit_cast(int16x4_t, lhs.to_native()),
151 __builtin_bit_cast(int16x8_t, rhs.to_native()));
153 }
154 }
155
157 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 4, Arch>); sizeof(simd<std::int16_t, 8, Arch>); })
159 simd<std::int16_t, 4, Arch> accumulator,
161 simd<std::int16_t, 8, Arch> rhs) noexcept {
162 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
163 }
164
166 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
167 native_nodiscard native_inline __attribute__((target("rdm")))
168 constexpr simd<std::int16_t, 8, Arch> sqrdmlah(
169 simd<std::int16_t, 8, Arch> accumulator,
170 simd<std::int16_t, 8, Arch> lhs,
171 simd<std::int16_t, 8, Arch> rhs) noexcept {
172 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
173 else {
174 auto result = detail::sqrdmlah<Arch>(
175 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
176 __builtin_bit_cast(int16x8_t, lhs.to_native()),
177 __builtin_bit_cast(int16x8_t, rhs.to_native()));
179 }
180 }
181
183 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int16_t, 8, Arch>); })
185 simd<std::int16_t, 8, Arch> accumulator,
187 simd<std::int16_t, 8, Arch> rhs) noexcept {
188 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
189 }
190
192 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
193 native_nodiscard native_inline __attribute__((target("rdm")))
194 constexpr simd<std::int16_t, 8, Arch> sqrdmlah_lane(
195 simd<std::int16_t, 8, Arch> accumulator,
196 simd<std::int16_t, 8, Arch> lhs,
197 simd<std::int16_t, 4, Arch> rhs) noexcept {
198 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
199 else {
200 auto result = detail::sqrdmlah_lane<Arch, Lane>(
201 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
202 __builtin_bit_cast(int16x8_t, lhs.to_native()),
203 __builtin_bit_cast(int16x4_t, rhs.to_native()));
205 }
206 }
207
209 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 8, Arch>); sizeof(simd<std::int16_t, 4, Arch>); })
211 simd<std::int16_t, 8, Arch> accumulator,
213 simd<std::int16_t, 4, Arch> rhs) noexcept {
214 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
215 }
216
218 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
219 native_nodiscard native_inline __attribute__((target("rdm")))
220 constexpr simd<std::int16_t, 8, Arch> sqrdmlah_lane(
221 simd<std::int16_t, 8, Arch> accumulator,
222 simd<std::int16_t, 8, Arch> lhs,
223 simd<std::int16_t, 8, Arch> rhs) noexcept {
224 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
225 else {
226 auto result = detail::sqrdmlah_lane<Arch, Lane>(
227 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
228 __builtin_bit_cast(int16x8_t, lhs.to_native()),
229 __builtin_bit_cast(int16x8_t, rhs.to_native()));
231 }
232 }
233
235 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 8, Arch>); })
237 simd<std::int16_t, 8, Arch> accumulator,
239 simd<std::int16_t, 8, Arch> rhs) noexcept {
240 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
241 }
242
244 template<isa<arm> Arch=NATIVE_BASELINE> requires(Arch.has(arm_feature::rdm))
245 native_nodiscard native_inline __attribute__((target("rdm")))
246 constexpr int32_t sqrdmlah(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
247 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
248 else {
249 auto result = detail::sqrdmlah<Arch>(
250 accumulator,
251 lhs,
252 rhs);
253 return result;
254 }
255 }
256
258 template<isa<arm> Arch=NATIVE_BASELINE> requires(!Arch.has(arm_feature::rdm))
259 native_nodiscard consteval int32_t sqrdmlah(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
260 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
261 }
262
264 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
265 native_nodiscard native_inline __attribute__((target("rdm")))
266 constexpr int32_t sqrdmlah_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 2, Arch> rhs) noexcept {
267 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
268 else {
269 auto result = detail::sqrdmlah_lane<Arch, Lane>(
270 accumulator,
271 lhs,
272 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
273 return result;
274 }
275 }
276
278 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 2, Arch>); })
279 native_nodiscard consteval int32_t sqrdmlah_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 2, Arch> rhs) noexcept {
280 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
281 }
282
284 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
285 native_nodiscard native_inline __attribute__((target("rdm")))
286 constexpr int32_t sqrdmlah_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 4, Arch> rhs) noexcept {
287 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
288 else {
289 auto result = detail::sqrdmlah_lane<Arch, Lane>(
290 accumulator,
291 lhs,
292 __builtin_bit_cast(int32x4_t, rhs.to_native()));
293 return result;
294 }
295 }
296
298 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 4, Arch>); })
299 native_nodiscard consteval int32_t sqrdmlah_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 4, Arch> rhs) noexcept {
300 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
301 }
302
304 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
305 native_nodiscard native_inline __attribute__((target("rdm")))
306 constexpr simd<std::int32_t, 2, Arch> sqrdmlah(
307 simd<std::int32_t, 2, Arch> accumulator,
308 simd<std::int32_t, 2, Arch> lhs,
309 simd<std::int32_t, 2, Arch> rhs) noexcept {
310 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
311 else {
312 auto result = detail::sqrdmlah<Arch>(
313 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
314 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
315 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
316 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
317 }
318 }
319
321 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int32_t, 2, Arch>); })
323 simd<std::int32_t, 2, Arch> accumulator,
325 simd<std::int32_t, 2, Arch> rhs) noexcept {
326 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
327 }
328
330 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
331 native_nodiscard native_inline __attribute__((target("rdm")))
332 constexpr simd<std::int32_t, 2, Arch> sqrdmlah_lane(
333 simd<std::int32_t, 2, Arch> accumulator,
334 simd<std::int32_t, 2, Arch> lhs,
335 simd<std::int32_t, 2, Arch> rhs) noexcept {
336 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
337 else {
338 auto result = detail::sqrdmlah_lane<Arch, Lane>(
339 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
340 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
341 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
342 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
343 }
344 }
345
347 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 2, Arch>); })
349 simd<std::int32_t, 2, Arch> accumulator,
351 simd<std::int32_t, 2, Arch> rhs) noexcept {
352 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
353 }
354
356 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
357 native_nodiscard native_inline __attribute__((target("rdm")))
358 constexpr simd<std::int32_t, 2, Arch> sqrdmlah_lane(
359 simd<std::int32_t, 2, Arch> accumulator,
360 simd<std::int32_t, 2, Arch> lhs,
361 simd<std::int32_t, 4, Arch> rhs) noexcept {
362 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
363 else {
364 auto result = detail::sqrdmlah_lane<Arch, Lane>(
365 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
366 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
367 __builtin_bit_cast(int32x4_t, rhs.to_native()));
368 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
369 }
370 }
371
373 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 2, Arch>); sizeof(simd<std::int32_t, 4, Arch>); })
375 simd<std::int32_t, 2, Arch> accumulator,
377 simd<std::int32_t, 4, Arch> rhs) noexcept {
378 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
379 }
380
382 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
383 native_nodiscard native_inline __attribute__((target("rdm")))
384 constexpr simd<std::int32_t, 4, Arch> sqrdmlah(
385 simd<std::int32_t, 4, Arch> accumulator,
386 simd<std::int32_t, 4, Arch> lhs,
387 simd<std::int32_t, 4, Arch> rhs) noexcept {
388 if consteval { return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs); }
389 else {
390 auto result = detail::sqrdmlah<Arch>(
391 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
392 __builtin_bit_cast(int32x4_t, lhs.to_native()),
393 __builtin_bit_cast(int32x4_t, rhs.to_native()));
395 }
396 }
397
399 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int32_t, 4, Arch>); })
401 simd<std::int32_t, 4, Arch> accumulator,
403 simd<std::int32_t, 4, Arch> rhs) noexcept {
404 return detail::arm_constant::rdm<false, -1>(accumulator, lhs, rhs);
405 }
406
408 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
409 native_nodiscard native_inline __attribute__((target("rdm")))
410 constexpr simd<std::int32_t, 4, Arch> sqrdmlah_lane(
411 simd<std::int32_t, 4, Arch> accumulator,
412 simd<std::int32_t, 4, Arch> lhs,
413 simd<std::int32_t, 2, Arch> rhs) noexcept {
414 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
415 else {
416 auto result = detail::sqrdmlah_lane<Arch, Lane>(
417 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
418 __builtin_bit_cast(int32x4_t, lhs.to_native()),
419 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
421 }
422 }
423
425 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 4, Arch>); sizeof(simd<std::int32_t, 2, Arch>); })
427 simd<std::int32_t, 4, Arch> accumulator,
429 simd<std::int32_t, 2, Arch> rhs) noexcept {
430 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
431 }
432
434 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
435 native_nodiscard native_inline __attribute__((target("rdm")))
436 constexpr simd<std::int32_t, 4, Arch> sqrdmlah_lane(
437 simd<std::int32_t, 4, Arch> accumulator,
438 simd<std::int32_t, 4, Arch> lhs,
439 simd<std::int32_t, 4, Arch> rhs) noexcept {
440 if consteval { return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs); }
441 else {
442 auto result = detail::sqrdmlah_lane<Arch, Lane>(
443 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
444 __builtin_bit_cast(int32x4_t, lhs.to_native()),
445 __builtin_bit_cast(int32x4_t, rhs.to_native()));
447 }
448 }
449
451 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 4, Arch>); })
453 simd<std::int32_t, 4, Arch> accumulator,
455 simd<std::int32_t, 4, Arch> rhs) noexcept {
456 return detail::arm_constant::rdm<false, Lane>(accumulator, lhs, rhs);
457 }
458
460 template<isa<arm> Arch=NATIVE_BASELINE> requires(Arch.has(arm_feature::rdm))
461 native_nodiscard native_inline __attribute__((target("rdm")))
462 constexpr int16_t sqrdmlsh(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
463 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
464 else {
465 auto result = detail::sqrdmlsh<Arch>(
466 accumulator,
467 lhs,
468 rhs);
469 return result;
470 }
471 }
472
474 template<isa<arm> Arch=NATIVE_BASELINE> requires(!Arch.has(arm_feature::rdm))
475 native_nodiscard consteval int16_t sqrdmlsh(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
476 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
477 }
478
480 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
481 native_nodiscard native_inline __attribute__((target("rdm")))
482 constexpr int16_t sqrdmlsh_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 4, Arch> rhs) noexcept {
483 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
484 else {
485 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
486 accumulator,
487 lhs,
488 __builtin_bit_cast(int16x4_t, rhs.to_native()));
489 return result;
490 }
491 }
492
494 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 4, Arch>); })
495 native_nodiscard consteval int16_t sqrdmlsh_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 4, Arch> rhs) noexcept {
496 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
497 }
498
500 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
501 native_nodiscard native_inline __attribute__((target("rdm")))
502 constexpr int16_t sqrdmlsh_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 8, Arch> rhs) noexcept {
503 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
504 else {
505 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
506 accumulator,
507 lhs,
508 __builtin_bit_cast(int16x8_t, rhs.to_native()));
509 return result;
510 }
511 }
512
514 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 8, Arch>); })
515 native_nodiscard consteval int16_t sqrdmlsh_lane(int16_t accumulator, int16_t lhs, simd<std::int16_t, 8, Arch> rhs) noexcept {
516 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
517 }
518
520 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
521 native_nodiscard native_inline __attribute__((target("rdm")))
522 constexpr simd<std::int16_t, 4, Arch> sqrdmlsh(
523 simd<std::int16_t, 4, Arch> accumulator,
524 simd<std::int16_t, 4, Arch> lhs,
525 simd<std::int16_t, 4, Arch> rhs) noexcept {
526 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
527 else {
528 auto result = detail::sqrdmlsh<Arch>(
529 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
530 __builtin_bit_cast(int16x4_t, lhs.to_native()),
531 __builtin_bit_cast(int16x4_t, rhs.to_native()));
533 }
534 }
535
537 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int16_t, 4, Arch>); })
539 simd<std::int16_t, 4, Arch> accumulator,
541 simd<std::int16_t, 4, Arch> rhs) noexcept {
542 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
543 }
544
546 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
547 native_nodiscard native_inline __attribute__((target("rdm")))
548 constexpr simd<std::int16_t, 4, Arch> sqrdmlsh_lane(
549 simd<std::int16_t, 4, Arch> accumulator,
550 simd<std::int16_t, 4, Arch> lhs,
551 simd<std::int16_t, 4, Arch> rhs) noexcept {
552 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
553 else {
554 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
555 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
556 __builtin_bit_cast(int16x4_t, lhs.to_native()),
557 __builtin_bit_cast(int16x4_t, rhs.to_native()));
559 }
560 }
561
563 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 4, Arch>); })
565 simd<std::int16_t, 4, Arch> accumulator,
567 simd<std::int16_t, 4, Arch> rhs) noexcept {
568 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
569 }
570
572 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
573 native_nodiscard native_inline __attribute__((target("rdm")))
574 constexpr simd<std::int16_t, 4, Arch> sqrdmlsh_lane(
575 simd<std::int16_t, 4, Arch> accumulator,
576 simd<std::int16_t, 4, Arch> lhs,
577 simd<std::int16_t, 8, Arch> rhs) noexcept {
578 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
579 else {
580 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
581 __builtin_bit_cast(int16x4_t, accumulator.to_native()),
582 __builtin_bit_cast(int16x4_t, lhs.to_native()),
583 __builtin_bit_cast(int16x8_t, rhs.to_native()));
585 }
586 }
587
589 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 4, Arch>); sizeof(simd<std::int16_t, 8, Arch>); })
591 simd<std::int16_t, 4, Arch> accumulator,
593 simd<std::int16_t, 8, Arch> rhs) noexcept {
594 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
595 }
596
598 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
599 native_nodiscard native_inline __attribute__((target("rdm")))
600 constexpr simd<std::int16_t, 8, Arch> sqrdmlsh(
601 simd<std::int16_t, 8, Arch> accumulator,
602 simd<std::int16_t, 8, Arch> lhs,
603 simd<std::int16_t, 8, Arch> rhs) noexcept {
604 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
605 else {
606 auto result = detail::sqrdmlsh<Arch>(
607 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
608 __builtin_bit_cast(int16x8_t, lhs.to_native()),
609 __builtin_bit_cast(int16x8_t, rhs.to_native()));
611 }
612 }
613
615 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int16_t, 8, Arch>); })
617 simd<std::int16_t, 8, Arch> accumulator,
619 simd<std::int16_t, 8, Arch> rhs) noexcept {
620 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
621 }
622
624 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
625 native_nodiscard native_inline __attribute__((target("rdm")))
626 constexpr simd<std::int16_t, 8, Arch> sqrdmlsh_lane(
627 simd<std::int16_t, 8, Arch> accumulator,
628 simd<std::int16_t, 8, Arch> lhs,
629 simd<std::int16_t, 4, Arch> rhs) noexcept {
630 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
631 else {
632 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
633 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
634 __builtin_bit_cast(int16x8_t, lhs.to_native()),
635 __builtin_bit_cast(int16x4_t, rhs.to_native()));
637 }
638 }
639
641 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int16_t, 8, Arch>); sizeof(simd<std::int16_t, 4, Arch>); })
643 simd<std::int16_t, 8, Arch> accumulator,
645 simd<std::int16_t, 4, Arch> rhs) noexcept {
646 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
647 }
648
650 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
651 native_nodiscard native_inline __attribute__((target("rdm")))
652 constexpr simd<std::int16_t, 8, Arch> sqrdmlsh_lane(
653 simd<std::int16_t, 8, Arch> accumulator,
654 simd<std::int16_t, 8, Arch> lhs,
655 simd<std::int16_t, 8, Arch> rhs) noexcept {
656 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
657 else {
658 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
659 __builtin_bit_cast(int16x8_t, accumulator.to_native()),
660 __builtin_bit_cast(int16x8_t, lhs.to_native()),
661 __builtin_bit_cast(int16x8_t, rhs.to_native()));
663 }
664 }
665
667 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8 && requires { sizeof(simd<std::int16_t, 8, Arch>); })
669 simd<std::int16_t, 8, Arch> accumulator,
671 simd<std::int16_t, 8, Arch> rhs) noexcept {
672 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
673 }
674
676 template<isa<arm> Arch=NATIVE_BASELINE> requires(Arch.has(arm_feature::rdm))
677 native_nodiscard native_inline __attribute__((target("rdm")))
678 constexpr int32_t sqrdmlsh(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
679 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
680 else {
681 auto result = detail::sqrdmlsh<Arch>(
682 accumulator,
683 lhs,
684 rhs);
685 return result;
686 }
687 }
688
690 template<isa<arm> Arch=NATIVE_BASELINE> requires(!Arch.has(arm_feature::rdm))
691 native_nodiscard consteval int32_t sqrdmlsh(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
692 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
693 }
694
696 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
697 native_nodiscard native_inline __attribute__((target("rdm")))
698 constexpr int32_t sqrdmlsh_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 2, Arch> rhs) noexcept {
699 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
700 else {
701 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
702 accumulator,
703 lhs,
704 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
705 return result;
706 }
707 }
708
710 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 2, Arch>); })
711 native_nodiscard consteval int32_t sqrdmlsh_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 2, Arch> rhs) noexcept {
712 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
713 }
714
716 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
717 native_nodiscard native_inline __attribute__((target("rdm")))
718 constexpr int32_t sqrdmlsh_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 4, Arch> rhs) noexcept {
719 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
720 else {
721 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
722 accumulator,
723 lhs,
724 __builtin_bit_cast(int32x4_t, rhs.to_native()));
725 return result;
726 }
727 }
728
730 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 4, Arch>); })
731 native_nodiscard consteval int32_t sqrdmlsh_lane(int32_t accumulator, int32_t lhs, simd<std::int32_t, 4, Arch> rhs) noexcept {
732 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
733 }
734
736 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
737 native_nodiscard native_inline __attribute__((target("rdm")))
738 constexpr simd<std::int32_t, 2, Arch> sqrdmlsh(
739 simd<std::int32_t, 2, Arch> accumulator,
740 simd<std::int32_t, 2, Arch> lhs,
741 simd<std::int32_t, 2, Arch> rhs) noexcept {
742 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
743 else {
744 auto result = detail::sqrdmlsh<Arch>(
745 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
746 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
747 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
748 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
749 }
750 }
751
753 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int32_t, 2, Arch>); })
755 simd<std::int32_t, 2, Arch> accumulator,
757 simd<std::int32_t, 2, Arch> rhs) noexcept {
758 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
759 }
760
762 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
763 native_nodiscard native_inline __attribute__((target("rdm")))
764 constexpr simd<std::int32_t, 2, Arch> sqrdmlsh_lane(
765 simd<std::int32_t, 2, Arch> accumulator,
766 simd<std::int32_t, 2, Arch> lhs,
767 simd<std::int32_t, 2, Arch> rhs) noexcept {
768 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
769 else {
770 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
771 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
772 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
773 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
774 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
775 }
776 }
777
779 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 2, Arch>); })
781 simd<std::int32_t, 2, Arch> accumulator,
783 simd<std::int32_t, 2, Arch> rhs) noexcept {
784 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
785 }
786
788 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
789 native_nodiscard native_inline __attribute__((target("rdm")))
790 constexpr simd<std::int32_t, 2, Arch> sqrdmlsh_lane(
791 simd<std::int32_t, 2, Arch> accumulator,
792 simd<std::int32_t, 2, Arch> lhs,
793 simd<std::int32_t, 4, Arch> rhs) noexcept {
794 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
795 else {
796 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
797 vget_low_s32(__builtin_bit_cast(int32x4_t, accumulator.to_native())),
798 vget_low_s32(__builtin_bit_cast(int32x4_t, lhs.to_native())),
799 __builtin_bit_cast(int32x4_t, rhs.to_native()));
800 return simd<std::int32_t, 2, Arch>::from_native(__builtin_bit_cast(typename simd<std::int32_t, 2, Arch>::native_type, vcombine_s32(result, vdup_n_s32(0))));
801 }
802 }
803
805 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 2, Arch>); sizeof(simd<std::int32_t, 4, Arch>); })
807 simd<std::int32_t, 2, Arch> accumulator,
809 simd<std::int32_t, 4, Arch> rhs) noexcept {
810 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
811 }
812
814 template<isa<arm> Arch> requires(Arch.has(arm_feature::rdm))
815 native_nodiscard native_inline __attribute__((target("rdm")))
816 constexpr simd<std::int32_t, 4, Arch> sqrdmlsh(
817 simd<std::int32_t, 4, Arch> accumulator,
818 simd<std::int32_t, 4, Arch> lhs,
819 simd<std::int32_t, 4, Arch> rhs) noexcept {
820 if consteval { return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs); }
821 else {
822 auto result = detail::sqrdmlsh<Arch>(
823 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
824 __builtin_bit_cast(int32x4_t, lhs.to_native()),
825 __builtin_bit_cast(int32x4_t, rhs.to_native()));
827 }
828 }
829
831 template<isa<arm> Arch> requires(!Arch.has(arm_feature::rdm) && requires { sizeof(simd<std::int32_t, 4, Arch>); })
833 simd<std::int32_t, 4, Arch> accumulator,
835 simd<std::int32_t, 4, Arch> rhs) noexcept {
836 return detail::arm_constant::rdm<true, -1>(accumulator, lhs, rhs);
837 }
838
840 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
841 native_nodiscard native_inline __attribute__((target("rdm")))
842 constexpr simd<std::int32_t, 4, Arch> sqrdmlsh_lane(
843 simd<std::int32_t, 4, Arch> accumulator,
844 simd<std::int32_t, 4, Arch> lhs,
845 simd<std::int32_t, 2, Arch> rhs) noexcept {
846 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
847 else {
848 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
849 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
850 __builtin_bit_cast(int32x4_t, lhs.to_native()),
851 vget_low_s32(__builtin_bit_cast(int32x4_t, rhs.to_native())));
853 }
854 }
855
857 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2 && requires { sizeof(simd<std::int32_t, 4, Arch>); sizeof(simd<std::int32_t, 2, Arch>); })
859 simd<std::int32_t, 4, Arch> accumulator,
861 simd<std::int32_t, 2, Arch> rhs) noexcept {
862 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
863 }
864
866 template<isa<arm> Arch, int Lane> requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
867 native_nodiscard native_inline __attribute__((target("rdm")))
868 constexpr simd<std::int32_t, 4, Arch> sqrdmlsh_lane(
869 simd<std::int32_t, 4, Arch> accumulator,
870 simd<std::int32_t, 4, Arch> lhs,
871 simd<std::int32_t, 4, Arch> rhs) noexcept {
872 if consteval { return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs); }
873 else {
874 auto result = detail::sqrdmlsh_lane<Arch, Lane>(
875 __builtin_bit_cast(int32x4_t, accumulator.to_native()),
876 __builtin_bit_cast(int32x4_t, lhs.to_native()),
877 __builtin_bit_cast(int32x4_t, rhs.to_native()));
879 }
880 }
881
883 template<isa<arm> Arch, int Lane> requires(!Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4 && requires { sizeof(simd<std::int32_t, 4, Arch>); })
885 simd<std::int32_t, 4, Arch> accumulator,
887 simd<std::int32_t, 4, Arch> rhs) noexcept {
888 return detail::arm_constant::rdm<true, Lane>(accumulator, lhs, rhs);
889 }
890
892 template<isa<arm> Arch=NATIVE_BASELINE, class A, class B, class C>
893 void sqrdmlah(A, B, C) = delete;
894 template<isa<arm> Arch, int Lane, class A, class B, class C>
895 void sqrdmlah_lane(A, B, C) = delete;
896 template<isa<arm> Arch=NATIVE_BASELINE, class A, class B, class C>
897 void sqrdmlsh(A, B, C) = delete;
898 template<isa<arm> Arch, int Lane, class A, class B, class C>
899 void sqrdmlsh_lane(A, B, C) = delete;
902}
903#endif
904}
constexpr int16_t sqrdmlah(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept
SQRDMLAH: signed 16-bit rounding saturating add.
constexpr int16_t sqrdmlah_lane(int16_t accumulator, int16_t lhs, simd< std::int16_t, 4, Arch > rhs) noexcept
SQRDMLAH by element: broadcast rhs[Lane] before rounding and saturation.
constexpr int16_t sqrdmlsh_lane(int16_t accumulator, int16_t lhs, simd< std::int16_t, 4, Arch > rhs) noexcept
SQRDMLSH by element: broadcast rhs[Lane] before rounding and saturation.
constexpr int16_t sqrdmlsh(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept
SQRDMLSH: signed 16-bit rounding saturating subtract.
#define native_inline
inline [[always_inline]]
Definition attributes.h:212
#define native_nodiscard
C++17 [[nodiscard]].
Definition attributes.h:189
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
constexpr int target
First matching requirement, with every later choice checked for shadowing.
Definition isa.h:396
Standard-library adaptations documented here for SIMD value types.
Omitted architecture arguments use the native.simd provider's baseline.