5#include "native/config.h"
11#if NATIVE_HOST_NEON || defined(NATIVE_DOXYGEN)
13namespace native::detail {
17 template<
class V>
native_inline V rdm_register_order(V value)
noexcept {
18#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
19 if constexpr (
requires { value[0]; }) {
20 if constexpr (
sizeof(V) == 16) {
21 auto bytes = __builtin_bit_cast(int8x16_t, value);
22 if constexpr (
sizeof(value[0]) == 2)
23 return __builtin_bit_cast(V, __builtin_shufflevector(bytes, bytes,
24 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14));
26 return __builtin_bit_cast(V, __builtin_shufflevector(bytes, bytes,
27 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12));
34 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
36 int16_t
sqrdmlah(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
37 auto result = detail::rdm_register_order(accumulator);
38 auto left = detail::rdm_register_order(lhs);
39 auto right = detail::rdm_register_order(rhs);
40 asm volatile(
"sqrdmlah %h0, %h1, %h2"
41 :
"+w"(result) :
"w"(left),
"w"(right));
42 return detail::rdm_register_order(result);
45 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
47 int16_t
sqrdmlah_lane(int16_t accumulator, int16_t lhs, int16x4_t rhs) noexcept {
48 auto result = detail::rdm_register_order(accumulator);
49 auto left = detail::rdm_register_order(lhs);
50 auto right = detail::rdm_register_order(rhs);
52 auto source = detail::rdm_register_order(
53 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
54#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
55 constexpr int index = 3 - Lane;
57 constexpr int index = Lane;
59 asm volatile(
"sqrdmlah %h0, %h1, %2.h[%c3]"
60 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
61 return detail::rdm_register_order(result);
64 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
66 int16_t
sqrdmlah_lane(int16_t accumulator, int16_t lhs, int16x8_t rhs) noexcept {
67 auto result = detail::rdm_register_order(accumulator);
68 auto left = detail::rdm_register_order(lhs);
69 auto right = detail::rdm_register_order(rhs);
70#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
71 constexpr int index = 7 - Lane;
73 constexpr int index = Lane;
75 asm volatile(
"sqrdmlah %h0, %h1, %2.h[%c3]"
76 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
77 return detail::rdm_register_order(result);
80 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
82 int16x4_t
sqrdmlah(int16x4_t accumulator, int16x4_t lhs, int16x4_t rhs) noexcept {
83 auto result = detail::rdm_register_order(accumulator);
84 auto left = detail::rdm_register_order(lhs);
85 auto right = detail::rdm_register_order(rhs);
86 asm volatile(
"sqrdmlah %0.4h, %1.4h, %2.4h"
87 :
"+w"(result) :
"w"(left),
"w"(right));
88 return detail::rdm_register_order(result);
91 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
93 int16x4_t
sqrdmlah_lane(int16x4_t accumulator, int16x4_t lhs, int16x4_t rhs) noexcept {
94 auto result = detail::rdm_register_order(accumulator);
95 auto left = detail::rdm_register_order(lhs);
96 auto right = detail::rdm_register_order(rhs);
98 auto source = detail::rdm_register_order(
99 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
100#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
101 constexpr int index = 3 - Lane;
103 constexpr int index = Lane;
105 asm volatile(
"sqrdmlah %0.4h, %1.4h, %2.h[%c3]"
106 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
107 return detail::rdm_register_order(result);
110 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
112 int16x4_t
sqrdmlah_lane(int16x4_t accumulator, int16x4_t lhs, int16x8_t rhs) noexcept {
113 auto result = detail::rdm_register_order(accumulator);
114 auto left = detail::rdm_register_order(lhs);
115 auto right = detail::rdm_register_order(rhs);
116#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
117 constexpr int index = 7 - Lane;
119 constexpr int index = Lane;
121 asm volatile(
"sqrdmlah %0.4h, %1.4h, %2.h[%c3]"
122 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
123 return detail::rdm_register_order(result);
126 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
128 int16x8_t
sqrdmlah(int16x8_t accumulator, int16x8_t lhs, int16x8_t rhs) noexcept {
129 auto result = detail::rdm_register_order(accumulator);
130 auto left = detail::rdm_register_order(lhs);
131 auto right = detail::rdm_register_order(rhs);
132 asm volatile(
"sqrdmlah %0.8h, %1.8h, %2.8h"
133 :
"+w"(result) :
"w"(left),
"w"(right));
134 return detail::rdm_register_order(result);
137 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
139 int16x8_t
sqrdmlah_lane(int16x8_t accumulator, int16x8_t lhs, int16x4_t rhs) noexcept {
140 auto result = detail::rdm_register_order(accumulator);
141 auto left = detail::rdm_register_order(lhs);
142 auto right = detail::rdm_register_order(rhs);
144 auto source = detail::rdm_register_order(
145 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
146#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
147 constexpr int index = 3 - Lane;
149 constexpr int index = Lane;
151 asm volatile(
"sqrdmlah %0.8h, %1.8h, %2.h[%c3]"
152 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
153 return detail::rdm_register_order(result);
156 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
158 int16x8_t
sqrdmlah_lane(int16x8_t accumulator, int16x8_t lhs, int16x8_t rhs) noexcept {
159 auto result = detail::rdm_register_order(accumulator);
160 auto left = detail::rdm_register_order(lhs);
161 auto right = detail::rdm_register_order(rhs);
162#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
163 constexpr int index = 7 - Lane;
165 constexpr int index = Lane;
167 asm volatile(
"sqrdmlah %0.8h, %1.8h, %2.h[%c3]"
168 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
169 return detail::rdm_register_order(result);
172 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
174 int32_t
sqrdmlah(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
175 auto result = detail::rdm_register_order(accumulator);
176 auto left = detail::rdm_register_order(lhs);
177 auto right = detail::rdm_register_order(rhs);
178 asm volatile(
"sqrdmlah %s0, %s1, %s2"
179 :
"+w"(result) :
"w"(left),
"w"(right));
180 return detail::rdm_register_order(result);
183 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
185 int32_t
sqrdmlah_lane(int32_t accumulator, int32_t lhs, int32x2_t rhs) noexcept {
186 auto result = detail::rdm_register_order(accumulator);
187 auto left = detail::rdm_register_order(lhs);
188 auto right = detail::rdm_register_order(rhs);
189 constexpr int index = Lane;
190 asm volatile(
"sqrdmlah %s0, %s1, %2.s[%c3]"
191 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
192 return detail::rdm_register_order(result);
195 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
197 int32_t
sqrdmlah_lane(int32_t accumulator, int32_t lhs, int32x4_t rhs) noexcept {
198 auto result = detail::rdm_register_order(accumulator);
199 auto left = detail::rdm_register_order(lhs);
200 auto right = detail::rdm_register_order(rhs);
201#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
202 constexpr int index = 3 - Lane;
204 constexpr int index = Lane;
206 asm volatile(
"sqrdmlah %s0, %s1, %2.s[%c3]"
207 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
208 return detail::rdm_register_order(result);
211 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
213 int32x2_t
sqrdmlah(int32x2_t accumulator, int32x2_t lhs, int32x2_t rhs) noexcept {
214 auto result = detail::rdm_register_order(accumulator);
215 auto left = detail::rdm_register_order(lhs);
216 auto right = detail::rdm_register_order(rhs);
217 asm volatile(
"sqrdmlah %0.2s, %1.2s, %2.2s"
218 :
"+w"(result) :
"w"(left),
"w"(right));
219 return detail::rdm_register_order(result);
222 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
224 int32x2_t
sqrdmlah_lane(int32x2_t accumulator, int32x2_t lhs, int32x2_t rhs) noexcept {
225 auto result = detail::rdm_register_order(accumulator);
226 auto left = detail::rdm_register_order(lhs);
227 auto right = detail::rdm_register_order(rhs);
228 constexpr int index = Lane;
229 asm volatile(
"sqrdmlah %0.2s, %1.2s, %2.s[%c3]"
230 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
231 return detail::rdm_register_order(result);
234 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
236 int32x2_t
sqrdmlah_lane(int32x2_t accumulator, int32x2_t lhs, int32x4_t rhs) noexcept {
237 auto result = detail::rdm_register_order(accumulator);
238 auto left = detail::rdm_register_order(lhs);
239 auto right = detail::rdm_register_order(rhs);
240#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
241 constexpr int index = 3 - Lane;
243 constexpr int index = Lane;
245 asm volatile(
"sqrdmlah %0.2s, %1.2s, %2.s[%c3]"
246 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
247 return detail::rdm_register_order(result);
250 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
252 int32x4_t
sqrdmlah(int32x4_t accumulator, int32x4_t lhs, int32x4_t rhs) noexcept {
253 auto result = detail::rdm_register_order(accumulator);
254 auto left = detail::rdm_register_order(lhs);
255 auto right = detail::rdm_register_order(rhs);
256 asm volatile(
"sqrdmlah %0.4s, %1.4s, %2.4s"
257 :
"+w"(result) :
"w"(left),
"w"(right));
258 return detail::rdm_register_order(result);
261 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
263 int32x4_t
sqrdmlah_lane(int32x4_t accumulator, int32x4_t lhs, int32x2_t rhs) noexcept {
264 auto result = detail::rdm_register_order(accumulator);
265 auto left = detail::rdm_register_order(lhs);
266 auto right = detail::rdm_register_order(rhs);
267 constexpr int index = Lane;
268 asm volatile(
"sqrdmlah %0.4s, %1.4s, %2.s[%c3]"
269 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
270 return detail::rdm_register_order(result);
273 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
275 int32x4_t
sqrdmlah_lane(int32x4_t accumulator, int32x4_t lhs, int32x4_t rhs) noexcept {
276 auto result = detail::rdm_register_order(accumulator);
277 auto left = detail::rdm_register_order(lhs);
278 auto right = detail::rdm_register_order(rhs);
279#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
280 constexpr int index = 3 - Lane;
282 constexpr int index = Lane;
284 asm volatile(
"sqrdmlah %0.4s, %1.4s, %2.s[%c3]"
285 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
286 return detail::rdm_register_order(result);
289 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
291 int16_t
sqrdmlsh(int16_t accumulator, int16_t lhs, int16_t rhs) noexcept {
292 auto result = detail::rdm_register_order(accumulator);
293 auto left = detail::rdm_register_order(lhs);
294 auto right = detail::rdm_register_order(rhs);
295 asm volatile(
"sqrdmlsh %h0, %h1, %h2"
296 :
"+w"(result) :
"w"(left),
"w"(right));
297 return detail::rdm_register_order(result);
300 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
302 int16_t
sqrdmlsh_lane(int16_t accumulator, int16_t lhs, int16x4_t rhs) noexcept {
303 auto result = detail::rdm_register_order(accumulator);
304 auto left = detail::rdm_register_order(lhs);
305 auto right = detail::rdm_register_order(rhs);
307 auto source = detail::rdm_register_order(
308 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
309#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
310 constexpr int index = 3 - Lane;
312 constexpr int index = Lane;
314 asm volatile(
"sqrdmlsh %h0, %h1, %2.h[%c3]"
315 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
316 return detail::rdm_register_order(result);
319 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
321 int16_t
sqrdmlsh_lane(int16_t accumulator, int16_t lhs, int16x8_t rhs) noexcept {
322 auto result = detail::rdm_register_order(accumulator);
323 auto left = detail::rdm_register_order(lhs);
324 auto right = detail::rdm_register_order(rhs);
325#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
326 constexpr int index = 7 - Lane;
328 constexpr int index = Lane;
330 asm volatile(
"sqrdmlsh %h0, %h1, %2.h[%c3]"
331 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
332 return detail::rdm_register_order(result);
335 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
337 int16x4_t
sqrdmlsh(int16x4_t accumulator, int16x4_t lhs, int16x4_t rhs) noexcept {
338 auto result = detail::rdm_register_order(accumulator);
339 auto left = detail::rdm_register_order(lhs);
340 auto right = detail::rdm_register_order(rhs);
341 asm volatile(
"sqrdmlsh %0.4h, %1.4h, %2.4h"
342 :
"+w"(result) :
"w"(left),
"w"(right));
343 return detail::rdm_register_order(result);
346 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
348 int16x4_t
sqrdmlsh_lane(int16x4_t accumulator, int16x4_t lhs, int16x4_t rhs) noexcept {
349 auto result = detail::rdm_register_order(accumulator);
350 auto left = detail::rdm_register_order(lhs);
351 auto right = detail::rdm_register_order(rhs);
353 auto source = detail::rdm_register_order(
354 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
355#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
356 constexpr int index = 3 - Lane;
358 constexpr int index = Lane;
360 asm volatile(
"sqrdmlsh %0.4h, %1.4h, %2.h[%c3]"
361 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
362 return detail::rdm_register_order(result);
365 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
367 int16x4_t
sqrdmlsh_lane(int16x4_t accumulator, int16x4_t lhs, int16x8_t rhs) noexcept {
368 auto result = detail::rdm_register_order(accumulator);
369 auto left = detail::rdm_register_order(lhs);
370 auto right = detail::rdm_register_order(rhs);
371#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
372 constexpr int index = 7 - Lane;
374 constexpr int index = Lane;
376 asm volatile(
"sqrdmlsh %0.4h, %1.4h, %2.h[%c3]"
377 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
378 return detail::rdm_register_order(result);
381 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
383 int16x8_t
sqrdmlsh(int16x8_t accumulator, int16x8_t lhs, int16x8_t rhs) noexcept {
384 auto result = detail::rdm_register_order(accumulator);
385 auto left = detail::rdm_register_order(lhs);
386 auto right = detail::rdm_register_order(rhs);
387 asm volatile(
"sqrdmlsh %0.8h, %1.8h, %2.8h"
388 :
"+w"(result) :
"w"(left),
"w"(right));
389 return detail::rdm_register_order(result);
392 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
394 int16x8_t
sqrdmlsh_lane(int16x8_t accumulator, int16x8_t lhs, int16x4_t rhs) noexcept {
395 auto result = detail::rdm_register_order(accumulator);
396 auto left = detail::rdm_register_order(lhs);
397 auto right = detail::rdm_register_order(rhs);
399 auto source = detail::rdm_register_order(
400 __builtin_shufflevector(right, right, 0, 1, 2, 3, -1, -1, -1, -1));
401#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
402 constexpr int index = 3 - Lane;
404 constexpr int index = Lane;
406 asm volatile(
"sqrdmlsh %0.8h, %1.8h, %2.h[%c3]"
407 :
"+w"(result) :
"w"(left),
"x"(source),
"i"(index));
408 return detail::rdm_register_order(result);
411 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 8)
413 int16x8_t
sqrdmlsh_lane(int16x8_t accumulator, int16x8_t lhs, int16x8_t rhs) noexcept {
414 auto result = detail::rdm_register_order(accumulator);
415 auto left = detail::rdm_register_order(lhs);
416 auto right = detail::rdm_register_order(rhs);
417#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
418 constexpr int index = 7 - Lane;
420 constexpr int index = Lane;
422 asm volatile(
"sqrdmlsh %0.8h, %1.8h, %2.h[%c3]"
423 :
"+w"(result) :
"w"(left),
"x"(right),
"i"(index));
424 return detail::rdm_register_order(result);
427 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
429 int32_t
sqrdmlsh(int32_t accumulator, int32_t lhs, int32_t rhs) noexcept {
430 auto result = detail::rdm_register_order(accumulator);
431 auto left = detail::rdm_register_order(lhs);
432 auto right = detail::rdm_register_order(rhs);
433 asm volatile(
"sqrdmlsh %s0, %s1, %s2"
434 :
"+w"(result) :
"w"(left),
"w"(right));
435 return detail::rdm_register_order(result);
438 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
440 int32_t
sqrdmlsh_lane(int32_t accumulator, int32_t lhs, int32x2_t rhs) noexcept {
441 auto result = detail::rdm_register_order(accumulator);
442 auto left = detail::rdm_register_order(lhs);
443 auto right = detail::rdm_register_order(rhs);
444 constexpr int index = Lane;
445 asm volatile(
"sqrdmlsh %s0, %s1, %2.s[%c3]"
446 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
447 return detail::rdm_register_order(result);
450 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
452 int32_t
sqrdmlsh_lane(int32_t accumulator, int32_t lhs, int32x4_t rhs) noexcept {
453 auto result = detail::rdm_register_order(accumulator);
454 auto left = detail::rdm_register_order(lhs);
455 auto right = detail::rdm_register_order(rhs);
456#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
457 constexpr int index = 3 - Lane;
459 constexpr int index = Lane;
461 asm volatile(
"sqrdmlsh %s0, %s1, %2.s[%c3]"
462 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
463 return detail::rdm_register_order(result);
466 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
468 int32x2_t
sqrdmlsh(int32x2_t accumulator, int32x2_t lhs, int32x2_t rhs) noexcept {
469 auto result = detail::rdm_register_order(accumulator);
470 auto left = detail::rdm_register_order(lhs);
471 auto right = detail::rdm_register_order(rhs);
472 asm volatile(
"sqrdmlsh %0.2s, %1.2s, %2.2s"
473 :
"+w"(result) :
"w"(left),
"w"(right));
474 return detail::rdm_register_order(result);
477 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
479 int32x2_t
sqrdmlsh_lane(int32x2_t accumulator, int32x2_t lhs, int32x2_t rhs) noexcept {
480 auto result = detail::rdm_register_order(accumulator);
481 auto left = detail::rdm_register_order(lhs);
482 auto right = detail::rdm_register_order(rhs);
483 constexpr int index = Lane;
484 asm volatile(
"sqrdmlsh %0.2s, %1.2s, %2.s[%c3]"
485 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
486 return detail::rdm_register_order(result);
489 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
491 int32x2_t
sqrdmlsh_lane(int32x2_t accumulator, int32x2_t lhs, int32x4_t rhs) noexcept {
492 auto result = detail::rdm_register_order(accumulator);
493 auto left = detail::rdm_register_order(lhs);
494 auto right = detail::rdm_register_order(rhs);
495#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
496 constexpr int index = 3 - Lane;
498 constexpr int index = Lane;
500 asm volatile(
"sqrdmlsh %0.2s, %1.2s, %2.s[%c3]"
501 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
502 return detail::rdm_register_order(result);
505 template<isa<arm> Arch>
requires(Arch.has(arm_feature::rdm))
507 int32x4_t
sqrdmlsh(int32x4_t accumulator, int32x4_t lhs, int32x4_t rhs) noexcept {
508 auto result = detail::rdm_register_order(accumulator);
509 auto left = detail::rdm_register_order(lhs);
510 auto right = detail::rdm_register_order(rhs);
511 asm volatile(
"sqrdmlsh %0.4s, %1.4s, %2.4s"
512 :
"+w"(result) :
"w"(left),
"w"(right));
513 return detail::rdm_register_order(result);
516 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 2)
518 int32x4_t
sqrdmlsh_lane(int32x4_t accumulator, int32x4_t lhs, int32x2_t rhs) noexcept {
519 auto result = detail::rdm_register_order(accumulator);
520 auto left = detail::rdm_register_order(lhs);
521 auto right = detail::rdm_register_order(rhs);
522 constexpr int index = Lane;
523 asm volatile(
"sqrdmlsh %0.4s, %1.4s, %2.s[%c3]"
524 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
525 return detail::rdm_register_order(result);
528 template<isa<arm> Arch,
int Lane>
requires(Arch.has(arm_feature::rdm) && Lane >= 0 && Lane < 4)
530 int32x4_t
sqrdmlsh_lane(int32x4_t accumulator, int32x4_t lhs, int32x4_t rhs) noexcept {
531 auto result = detail::rdm_register_order(accumulator);
532 auto left = detail::rdm_register_order(lhs);
533 auto right = detail::rdm_register_order(rhs);
534#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
535 constexpr int index = 3 - Lane;
537 constexpr int index = Lane;
539 asm volatile(
"sqrdmlsh %0.4s, %1.4s, %2.s[%c3]"
540 :
"+w"(result) :
"w"(left),
"w"(right),
"i"(index));
541 return detail::rdm_register_order(result);
547 template<isa<arm> Arch,
class A,
class B,
class C>
549 template<isa<arm> Arch,
int Lane,
class A,
class B,
class C>
551 template<isa<arm> Arch,
class A,
class B,
class C>
553 template<isa<arm> Arch,
int Lane,
class A,
class B,
class C>
Compiler attributes for host code, with shader-safe shared modifiers.
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]]
#define native_nodiscard
C++17 [[nodiscard]].
constexpr int target
First matching requirement, with every later choice checked for shadowing.