4#include "native/config.h"
7#include "native/arm/detail/register_order.h"
11#if NATIVE_HOST_NEON || defined(NATIVE_DOXYGEN)
12namespace native::detail {
22 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
23 && (Rotation == 90 || Rotation == 270))
25 float32x2_t
fcadd(float32x2_t a, float32x2_t b) noexcept {
26 a = detail::arm_register_order(a);
27 b = detail::arm_register_order(b);
29 asm volatile(
"fcadd %0.2s, %1.2s, %2.2s, #%3"
30 :
"=w"(result) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
31 return detail::arm_register_order(result);
34 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
35 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270))
37 float32x2_t
fcmla(float32x2_t acc, float32x2_t a, float32x2_t b) noexcept {
38 a = detail::arm_register_order(a);
39 b = detail::arm_register_order(b);
40 acc = detail::arm_register_order(acc);
41 asm volatile(
"fcmla %0.2s, %1.2s, %2.2s, #%3"
42 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
43 return detail::arm_register_order(acc);
46 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
47 requires(Arch.has(arm_feature::complxnum)
48 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
51 float32x2_t
fcmla_lane(float32x2_t acc, float32x2_t a, float32x2_t b) noexcept {
55 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
56 requires(Arch.has(arm_feature::complxnum)
57 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
60 float32x2_t
fcmla_lane(float32x2_t acc, float32x2_t a, float32x4_t b) noexcept {
61 if constexpr(Lane == 0)
67 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
68 && (Rotation == 90 || Rotation == 270))
70 float32x4_t
fcadd(float32x4_t a, float32x4_t b) noexcept {
71 a = detail::arm_register_order(a);
72 b = detail::arm_register_order(b);
74 asm volatile(
"fcadd %0.4s, %1.4s, %2.4s, #%3"
75 :
"=w"(result) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
76 return detail::arm_register_order(result);
79 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
80 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270))
82 float32x4_t
fcmla(float32x4_t acc, float32x4_t a, float32x4_t b) noexcept {
83 a = detail::arm_register_order(a);
84 b = detail::arm_register_order(b);
85 acc = detail::arm_register_order(acc);
86 asm volatile(
"fcmla %0.4s, %1.4s, %2.4s, #%3"
87 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
88 return detail::arm_register_order(acc);
91 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
92 requires(Arch.has(arm_feature::complxnum)
93 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
96 float32x4_t
fcmla_lane(float32x4_t acc, float32x4_t a, float32x2_t b) noexcept {
97 acc = detail::arm_register_order(acc);
98 a = detail::arm_register_order(a);
99 b = detail::arm_register_order(b);
100 asm volatile(
"fcmla %0.4s, %1.4s, %2.s[%3], #%4"
101 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane),
"i"(Rotation) :
"memory");
102 return detail::arm_register_order(acc);
105 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
106 requires(Arch.has(arm_feature::complxnum)
107 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
110 float32x4_t
fcmla_lane(float32x4_t acc, float32x4_t a, float32x4_t b) noexcept {
111 acc = detail::arm_register_order(acc);
112 a = detail::arm_register_order(a);
113 b = detail::arm_register_order(b);
114 asm volatile(
"fcmla %0.4s, %1.4s, %2.s[%3], #%4"
115 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane),
"i"(Rotation) :
"memory");
116 return detail::arm_register_order(acc);
119 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
120 && (Rotation == 90 || Rotation == 270))
122 float64x2_t
fcadd(float64x2_t a, float64x2_t b) noexcept {
123 a = detail::arm_register_order(a);
124 b = detail::arm_register_order(b);
126 asm volatile(
"fcadd %0.2d, %1.2d, %2.2d, #%3"
127 :
"=w"(result) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
128 return detail::arm_register_order(result);
131 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum)
132 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270))
134 float64x2_t
fcmla(float64x2_t acc, float64x2_t a, float64x2_t b) noexcept {
135 a = detail::arm_register_order(a);
136 b = detail::arm_register_order(b);
137 acc = detail::arm_register_order(acc);
138 asm volatile(
"fcmla %0.2d, %1.2d, %2.2d, #%3"
139 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
140 return detail::arm_register_order(acc);
143 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
144 && (Rotation == 90 || Rotation == 270))
146 float16x4_t
fcadd(float16x4_t a, float16x4_t b) noexcept {
147 a = detail::arm_register_order(a);
148 b = detail::arm_register_order(b);
150 asm volatile(
"fcadd %0.4h, %1.4h, %2.4h, #%3"
151 :
"=w"(result) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
152 return detail::arm_register_order(result);
155 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
156 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270))
158 float16x4_t
fcmla(float16x4_t acc, float16x4_t a, float16x4_t b) noexcept {
159 a = detail::arm_register_order(a);
160 b = detail::arm_register_order(b);
161 acc = detail::arm_register_order(acc);
162 asm volatile(
"fcmla %0.4h, %1.4h, %2.4h, #%3"
163 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
164 return detail::arm_register_order(acc);
167 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
168 requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
169 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
172 float16x4_t
fcmla_lane(float16x4_t acc, float16x4_t a, float16x4_t b) noexcept {
173 acc = detail::arm_register_order(acc);
174 a = detail::arm_register_order(a);
175 b = detail::arm_register_order(b);
176 asm volatile(
"fcmla %0.4h, %1.4h, %2.h[%3], #%4"
177 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane),
"i"(Rotation) :
"memory");
178 return detail::arm_register_order(acc);
181 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
182 requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
183 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
186 float16x4_t
fcmla_lane(float16x4_t acc, float16x4_t a, float16x8_t b) noexcept {
188 if constexpr(Lane >= 2)
189 return fcmla_lane<Arch, Rotation, Lane - 2>(acc, a, vget_high_f16(b));
190 acc = detail::arm_register_order(acc);
191 a = detail::arm_register_order(a);
192 b = detail::arm_register_order(b);
193 asm volatile(
"fcmla %0.4h, %1.4h, %2.h[%3], #%4"
194 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane % 2),
"i"(Rotation) :
"memory");
195 return detail::arm_register_order(acc);
198 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
199 && (Rotation == 90 || Rotation == 270))
201 float16x8_t
fcadd(float16x8_t a, float16x8_t b) noexcept {
202 a = detail::arm_register_order(a);
203 b = detail::arm_register_order(b);
205 asm volatile(
"fcadd %0.8h, %1.8h, %2.8h, #%3"
206 :
"=w"(result) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
207 return detail::arm_register_order(result);
210 template<isa<arm> Arch,
unsigned Rotation>
requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
211 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270))
213 float16x8_t
fcmla(float16x8_t acc, float16x8_t a, float16x8_t b) noexcept {
214 a = detail::arm_register_order(a);
215 b = detail::arm_register_order(b);
216 acc = detail::arm_register_order(acc);
217 asm volatile(
"fcmla %0.8h, %1.8h, %2.8h, #%3"
218 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Rotation) :
"memory");
219 return detail::arm_register_order(acc);
222 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
223 requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
224 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
227 float16x8_t
fcmla_lane(float16x8_t acc, float16x8_t a, float16x4_t b) noexcept {
228 acc = detail::arm_register_order(acc);
229 a = detail::arm_register_order(a);
230 b = detail::arm_register_order(b);
231 asm volatile(
"fcmla %0.8h, %1.8h, %2.h[%3], #%4"
232 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane),
"i"(Rotation) :
"memory");
233 return detail::arm_register_order(acc);
236 template<isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
237 requires(Arch.has(arm_feature::complxnum) && Arch.has(arm_feature::neon_fp16)
238 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
241 float16x8_t
fcmla_lane(float16x8_t acc, float16x8_t a, float16x8_t b) noexcept {
242 acc = detail::arm_register_order(acc);
243 a = detail::arm_register_order(a);
244 b = detail::arm_register_order(b);
245 asm volatile(
"fcmla %0.8h, %1.8h, %2.h[%3], #%4"
246 :
"+w"(acc) :
"w"(a),
"w"(b),
"i"(Lane),
"i"(Rotation) :
"memory");
247 return detail::arm_register_order(acc);
253 template<isa<arm> Arch,
unsigned Rotation>
254 requires(!(Arch.has(arm_feature::complxnum)
255 && (Rotation == 90 || Rotation == 270)))
256 float32x2_t
fcadd(float32x2_t, float32x2_t) noexcept = delete;
258 template<
isa<arm> Arch,
unsigned Rotation>
260 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)))
261 float32x2_t
fcmla(float32x2_t, float32x2_t, float32x2_t) noexcept = delete;
263 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
265 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
267 float32x2_t
fcmla_lane(float32x2_t, float32x2_t, float32x2_t) noexcept = delete;
269 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
271 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
273 float32x2_t
fcmla_lane(float32x2_t, float32x2_t, float32x4_t) noexcept = delete;
275 template<
isa<arm> Arch,
unsigned Rotation>
277 && (Rotation == 90 || Rotation == 270)))
278 float32x4_t
fcadd(float32x4_t, float32x4_t) noexcept = delete;
280 template<
isa<arm> Arch,
unsigned Rotation>
282 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)))
283 float32x4_t
fcmla(float32x4_t, float32x4_t, float32x4_t) noexcept = delete;
285 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
287 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
289 float32x4_t
fcmla_lane(float32x4_t, float32x4_t, float32x2_t) noexcept = delete;
291 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
293 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
295 float32x4_t
fcmla_lane(float32x4_t, float32x4_t, float32x4_t) noexcept = delete;
297 template<
isa<arm> Arch,
unsigned Rotation>
299 && (Rotation == 90 || Rotation == 270)))
300 float64x2_t
fcadd(float64x2_t, float64x2_t) noexcept = delete;
302 template<
isa<arm> Arch,
unsigned Rotation>
304 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)))
305 float64x2_t
fcmla(float64x2_t, float64x2_t, float64x2_t) noexcept = delete;
307 template<
isa<arm> Arch,
unsigned Rotation>
309 && (Rotation == 90 || Rotation == 270)))
310 float16x4_t
fcadd(float16x4_t, float16x4_t) noexcept = delete;
312 template<
isa<arm> Arch,
unsigned Rotation>
314 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)))
315 float16x4_t
fcmla(float16x4_t, float16x4_t, float16x4_t) noexcept = delete;
317 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
319 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
321 float16x4_t
fcmla_lane(float16x4_t, float16x4_t, float16x4_t) noexcept = delete;
323 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
325 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
327 float16x4_t
fcmla_lane(float16x4_t, float16x4_t, float16x8_t) noexcept = delete;
329 template<
isa<arm> Arch,
unsigned Rotation>
331 && (Rotation == 90 || Rotation == 270)))
332 float16x8_t
fcadd(float16x8_t, float16x8_t) noexcept = delete;
334 template<
isa<arm> Arch,
unsigned Rotation>
336 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)))
337 float16x8_t
fcmla(float16x8_t, float16x8_t, float16x8_t) noexcept = delete;
339 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
341 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
343 float16x8_t
fcmla_lane(float16x8_t, float16x8_t, float16x4_t) noexcept = delete;
345 template<
isa<arm> Arch,
unsigned Rotation,
unsigned Lane>
347 && (Rotation == 0 || Rotation == 90 || Rotation == 180 || Rotation == 270)
349 float16x8_t
fcmla_lane(float16x8_t, float16x8_t, float16x8_t) noexcept = delete;
Compiler attributes for host code, with shader-safe shared modifiers.
constexpr simd< float, 2, Arch > fcmla_lane(simd< float, 2, Arch > acc, simd< float, 2, Arch > a, simd< float, 2, Arch > b) noexcept
FCMLA using complex pair Lane of b (the lane indexes pairs, not scalars).
constexpr simd< float, 2, Arch > fcadd(simd< float, 2, Arch > a, simd< float, 2, Arch > b) noexcept
FCADD on 1 binary32 complex pair(s), rotation in degrees.
constexpr simd< float, 2, Arch > fcmla(simd< float, 2, Arch > acc, simd< float, 2, Arch > a, simd< float, 2, Arch > b) noexcept
FCMLA on 1 binary32 complex pair(s), rotation in degrees.
#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.
arm_feature
Independently observable ARM instruction features, using local bit indices.
isa(E) -> isa< detail::family_of< E > >
Deduce the family from a feature enum; explicit isa<> always names the host family.