xref: /openbmc/qemu/target/arm/tcg/sve_helper.c (revision 2df1eb27)
1 /*
2  * ARM SVE Operations
3  *
4  * Copyright (c) 2018 Linaro, Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "internals.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
25 #include "tcg/tcg-gvec-desc.h"
26 #include "fpu/softfloat.h"
27 #include "tcg/tcg.h"
28 #include "vec_internal.h"
29 #include "sve_ldst_internal.h"
30 #include "hw/core/tcg-cpu-ops.h"
31 
32 
33 /* Return a value for NZCV as per the ARM PredTest pseudofunction.
34  *
35  * The return value has bit 31 set if N is set, bit 1 set if Z is clear,
36  * and bit 0 set if C is set.  Compare the definitions of these variables
37  * within CPUARMState.
38  */
39 
40 /* For no G bits set, NZCV = C.  */
41 #define PREDTEST_INIT  1
42 
43 /* This is an iterative function, called for each Pd and Pg word
44  * moving forward.
45  */
46 static uint32_t iter_predtest_fwd(uint64_t d, uint64_t g, uint32_t flags)
47 {
48     if (likely(g)) {
49         /* Compute N from first D & G.
50            Use bit 2 to signal first G bit seen.  */
51         if (!(flags & 4)) {
52             flags |= ((d & (g & -g)) != 0) << 31;
53             flags |= 4;
54         }
55 
56         /* Accumulate Z from each D & G.  */
57         flags |= ((d & g) != 0) << 1;
58 
59         /* Compute C from last !(D & G).  Replace previous.  */
60         flags = deposit32(flags, 0, 1, (d & pow2floor(g)) == 0);
61     }
62     return flags;
63 }
64 
65 /* This is an iterative function, called for each Pd and Pg word
66  * moving backward.
67  */
68 static uint32_t iter_predtest_bwd(uint64_t d, uint64_t g, uint32_t flags)
69 {
70     if (likely(g)) {
71         /* Compute C from first (i.e last) !(D & G).
72            Use bit 2 to signal first G bit seen.  */
73         if (!(flags & 4)) {
74             flags += 4 - 1; /* add bit 2, subtract C from PREDTEST_INIT */
75             flags |= (d & pow2floor(g)) == 0;
76         }
77 
78         /* Accumulate Z from each D & G.  */
79         flags |= ((d & g) != 0) << 1;
80 
81         /* Compute N from last (i.e first) D & G.  Replace previous.  */
82         flags = deposit32(flags, 31, 1, (d & (g & -g)) != 0);
83     }
84     return flags;
85 }
86 
87 /* The same for a single word predicate.  */
88 uint32_t HELPER(sve_predtest1)(uint64_t d, uint64_t g)
89 {
90     return iter_predtest_fwd(d, g, PREDTEST_INIT);
91 }
92 
93 /* The same for a multi-word predicate.  */
94 uint32_t HELPER(sve_predtest)(void *vd, void *vg, uint32_t words)
95 {
96     uint32_t flags = PREDTEST_INIT;
97     uint64_t *d = vd, *g = vg;
98     uintptr_t i = 0;
99 
100     do {
101         flags = iter_predtest_fwd(d[i], g[i], flags);
102     } while (++i < words);
103 
104     return flags;
105 }
106 
107 /* Similarly for single word elements.  */
108 static inline uint64_t expand_pred_s(uint8_t byte)
109 {
110     static const uint64_t word[] = {
111         [0x01] = 0x00000000ffffffffull,
112         [0x10] = 0xffffffff00000000ull,
113         [0x11] = 0xffffffffffffffffull,
114     };
115     return word[byte & 0x11];
116 }
117 
118 #define LOGICAL_PPPP(NAME, FUNC) \
119 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)  \
120 {                                                                         \
121     uintptr_t opr_sz = simd_oprsz(desc);                                  \
122     uint64_t *d = vd, *n = vn, *m = vm, *g = vg;                          \
123     uintptr_t i;                                                          \
124     for (i = 0; i < opr_sz / 8; ++i) {                                    \
125         d[i] = FUNC(n[i], m[i], g[i]);                                    \
126     }                                                                     \
127 }
128 
129 #define DO_AND(N, M, G)  (((N) & (M)) & (G))
130 #define DO_BIC(N, M, G)  (((N) & ~(M)) & (G))
131 #define DO_EOR(N, M, G)  (((N) ^ (M)) & (G))
132 #define DO_ORR(N, M, G)  (((N) | (M)) & (G))
133 #define DO_ORN(N, M, G)  (((N) | ~(M)) & (G))
134 #define DO_NOR(N, M, G)  (~((N) | (M)) & (G))
135 #define DO_NAND(N, M, G) (~((N) & (M)) & (G))
136 #define DO_SEL(N, M, G)  (((N) & (G)) | ((M) & ~(G)))
137 
138 LOGICAL_PPPP(sve_and_pppp, DO_AND)
139 LOGICAL_PPPP(sve_bic_pppp, DO_BIC)
140 LOGICAL_PPPP(sve_eor_pppp, DO_EOR)
141 LOGICAL_PPPP(sve_sel_pppp, DO_SEL)
142 LOGICAL_PPPP(sve_orr_pppp, DO_ORR)
143 LOGICAL_PPPP(sve_orn_pppp, DO_ORN)
144 LOGICAL_PPPP(sve_nor_pppp, DO_NOR)
145 LOGICAL_PPPP(sve_nand_pppp, DO_NAND)
146 
147 #undef DO_AND
148 #undef DO_BIC
149 #undef DO_EOR
150 #undef DO_ORR
151 #undef DO_ORN
152 #undef DO_NOR
153 #undef DO_NAND
154 #undef DO_SEL
155 #undef LOGICAL_PPPP
156 
157 /* Fully general three-operand expander, controlled by a predicate.
158  * This is complicated by the host-endian storage of the register file.
159  */
160 /* ??? I don't expect the compiler could ever vectorize this itself.
161  * With some tables we can convert bit masks to byte masks, and with
162  * extra care wrt byte/word ordering we could use gcc generic vectors
163  * and do 16 bytes at a time.
164  */
165 #define DO_ZPZZ(NAME, TYPE, H, OP)                                       \
166 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
167 {                                                                       \
168     intptr_t i, opr_sz = simd_oprsz(desc);                              \
169     for (i = 0; i < opr_sz; ) {                                         \
170         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));                 \
171         do {                                                            \
172             if (pg & 1) {                                               \
173                 TYPE nn = *(TYPE *)(vn + H(i));                         \
174                 TYPE mm = *(TYPE *)(vm + H(i));                         \
175                 *(TYPE *)(vd + H(i)) = OP(nn, mm);                      \
176             }                                                           \
177             i += sizeof(TYPE), pg >>= sizeof(TYPE);                     \
178         } while (i & 15);                                               \
179     }                                                                   \
180 }
181 
182 /* Similarly, specialized for 64-bit operands.  */
183 #define DO_ZPZZ_D(NAME, TYPE, OP)                                \
184 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
185 {                                                               \
186     intptr_t i, opr_sz = simd_oprsz(desc) / 8;                  \
187     TYPE *d = vd, *n = vn, *m = vm;                             \
188     uint8_t *pg = vg;                                           \
189     for (i = 0; i < opr_sz; i += 1) {                           \
190         if (pg[H1(i)] & 1) {                                    \
191             TYPE nn = n[i], mm = m[i];                          \
192             d[i] = OP(nn, mm);                                  \
193         }                                                       \
194     }                                                           \
195 }
196 
197 #define DO_AND(N, M)  (N & M)
198 #define DO_EOR(N, M)  (N ^ M)
199 #define DO_ORR(N, M)  (N | M)
200 #define DO_BIC(N, M)  (N & ~M)
201 #define DO_ADD(N, M)  (N + M)
202 #define DO_SUB(N, M)  (N - M)
203 #define DO_MAX(N, M)  ((N) >= (M) ? (N) : (M))
204 #define DO_MIN(N, M)  ((N) >= (M) ? (M) : (N))
205 #define DO_ABD(N, M)  ((N) >= (M) ? (N) - (M) : (M) - (N))
206 #define DO_MUL(N, M)  (N * M)
207 
208 
209 /*
210  * We must avoid the C undefined behaviour cases: division by
211  * zero and signed division of INT_MIN by -1. Both of these
212  * have architecturally defined required results for Arm.
213  * We special case all signed divisions by -1 to avoid having
214  * to deduce the minimum integer for the type involved.
215  */
216 #define DO_SDIV(N, M) (unlikely(M == 0) ? 0 : unlikely(M == -1) ? -N : N / M)
217 #define DO_UDIV(N, M) (unlikely(M == 0) ? 0 : N / M)
218 
219 DO_ZPZZ(sve_and_zpzz_b, uint8_t, H1, DO_AND)
220 DO_ZPZZ(sve_and_zpzz_h, uint16_t, H1_2, DO_AND)
221 DO_ZPZZ(sve_and_zpzz_s, uint32_t, H1_4, DO_AND)
222 DO_ZPZZ_D(sve_and_zpzz_d, uint64_t, DO_AND)
223 
224 DO_ZPZZ(sve_orr_zpzz_b, uint8_t, H1, DO_ORR)
225 DO_ZPZZ(sve_orr_zpzz_h, uint16_t, H1_2, DO_ORR)
226 DO_ZPZZ(sve_orr_zpzz_s, uint32_t, H1_4, DO_ORR)
227 DO_ZPZZ_D(sve_orr_zpzz_d, uint64_t, DO_ORR)
228 
229 DO_ZPZZ(sve_eor_zpzz_b, uint8_t, H1, DO_EOR)
230 DO_ZPZZ(sve_eor_zpzz_h, uint16_t, H1_2, DO_EOR)
231 DO_ZPZZ(sve_eor_zpzz_s, uint32_t, H1_4, DO_EOR)
232 DO_ZPZZ_D(sve_eor_zpzz_d, uint64_t, DO_EOR)
233 
234 DO_ZPZZ(sve_bic_zpzz_b, uint8_t, H1, DO_BIC)
235 DO_ZPZZ(sve_bic_zpzz_h, uint16_t, H1_2, DO_BIC)
236 DO_ZPZZ(sve_bic_zpzz_s, uint32_t, H1_4, DO_BIC)
237 DO_ZPZZ_D(sve_bic_zpzz_d, uint64_t, DO_BIC)
238 
239 DO_ZPZZ(sve_add_zpzz_b, uint8_t, H1, DO_ADD)
240 DO_ZPZZ(sve_add_zpzz_h, uint16_t, H1_2, DO_ADD)
241 DO_ZPZZ(sve_add_zpzz_s, uint32_t, H1_4, DO_ADD)
242 DO_ZPZZ_D(sve_add_zpzz_d, uint64_t, DO_ADD)
243 
244 DO_ZPZZ(sve_sub_zpzz_b, uint8_t, H1, DO_SUB)
245 DO_ZPZZ(sve_sub_zpzz_h, uint16_t, H1_2, DO_SUB)
246 DO_ZPZZ(sve_sub_zpzz_s, uint32_t, H1_4, DO_SUB)
247 DO_ZPZZ_D(sve_sub_zpzz_d, uint64_t, DO_SUB)
248 
249 DO_ZPZZ(sve_smax_zpzz_b, int8_t, H1, DO_MAX)
250 DO_ZPZZ(sve_smax_zpzz_h, int16_t, H1_2, DO_MAX)
251 DO_ZPZZ(sve_smax_zpzz_s, int32_t, H1_4, DO_MAX)
252 DO_ZPZZ_D(sve_smax_zpzz_d, int64_t, DO_MAX)
253 
254 DO_ZPZZ(sve_umax_zpzz_b, uint8_t, H1, DO_MAX)
255 DO_ZPZZ(sve_umax_zpzz_h, uint16_t, H1_2, DO_MAX)
256 DO_ZPZZ(sve_umax_zpzz_s, uint32_t, H1_4, DO_MAX)
257 DO_ZPZZ_D(sve_umax_zpzz_d, uint64_t, DO_MAX)
258 
259 DO_ZPZZ(sve_smin_zpzz_b, int8_t,  H1, DO_MIN)
260 DO_ZPZZ(sve_smin_zpzz_h, int16_t,  H1_2, DO_MIN)
261 DO_ZPZZ(sve_smin_zpzz_s, int32_t,  H1_4, DO_MIN)
262 DO_ZPZZ_D(sve_smin_zpzz_d, int64_t,  DO_MIN)
263 
264 DO_ZPZZ(sve_umin_zpzz_b, uint8_t, H1, DO_MIN)
265 DO_ZPZZ(sve_umin_zpzz_h, uint16_t, H1_2, DO_MIN)
266 DO_ZPZZ(sve_umin_zpzz_s, uint32_t, H1_4, DO_MIN)
267 DO_ZPZZ_D(sve_umin_zpzz_d, uint64_t, DO_MIN)
268 
269 DO_ZPZZ(sve_sabd_zpzz_b, int8_t,  H1, DO_ABD)
270 DO_ZPZZ(sve_sabd_zpzz_h, int16_t,  H1_2, DO_ABD)
271 DO_ZPZZ(sve_sabd_zpzz_s, int32_t,  H1_4, DO_ABD)
272 DO_ZPZZ_D(sve_sabd_zpzz_d, int64_t,  DO_ABD)
273 
274 DO_ZPZZ(sve_uabd_zpzz_b, uint8_t, H1, DO_ABD)
275 DO_ZPZZ(sve_uabd_zpzz_h, uint16_t, H1_2, DO_ABD)
276 DO_ZPZZ(sve_uabd_zpzz_s, uint32_t, H1_4, DO_ABD)
277 DO_ZPZZ_D(sve_uabd_zpzz_d, uint64_t, DO_ABD)
278 
279 /* Because the computation type is at least twice as large as required,
280    these work for both signed and unsigned source types.  */
281 static inline uint8_t do_mulh_b(int32_t n, int32_t m)
282 {
283     return (n * m) >> 8;
284 }
285 
286 static inline uint16_t do_mulh_h(int32_t n, int32_t m)
287 {
288     return (n * m) >> 16;
289 }
290 
291 static inline uint32_t do_mulh_s(int64_t n, int64_t m)
292 {
293     return (n * m) >> 32;
294 }
295 
296 static inline uint64_t do_smulh_d(uint64_t n, uint64_t m)
297 {
298     uint64_t lo, hi;
299     muls64(&lo, &hi, n, m);
300     return hi;
301 }
302 
303 static inline uint64_t do_umulh_d(uint64_t n, uint64_t m)
304 {
305     uint64_t lo, hi;
306     mulu64(&lo, &hi, n, m);
307     return hi;
308 }
309 
310 DO_ZPZZ(sve_mul_zpzz_b, uint8_t, H1, DO_MUL)
311 DO_ZPZZ(sve_mul_zpzz_h, uint16_t, H1_2, DO_MUL)
312 DO_ZPZZ(sve_mul_zpzz_s, uint32_t, H1_4, DO_MUL)
313 DO_ZPZZ_D(sve_mul_zpzz_d, uint64_t, DO_MUL)
314 
315 DO_ZPZZ(sve_smulh_zpzz_b, int8_t, H1, do_mulh_b)
316 DO_ZPZZ(sve_smulh_zpzz_h, int16_t, H1_2, do_mulh_h)
317 DO_ZPZZ(sve_smulh_zpzz_s, int32_t, H1_4, do_mulh_s)
318 DO_ZPZZ_D(sve_smulh_zpzz_d, uint64_t, do_smulh_d)
319 
320 DO_ZPZZ(sve_umulh_zpzz_b, uint8_t, H1, do_mulh_b)
321 DO_ZPZZ(sve_umulh_zpzz_h, uint16_t, H1_2, do_mulh_h)
322 DO_ZPZZ(sve_umulh_zpzz_s, uint32_t, H1_4, do_mulh_s)
323 DO_ZPZZ_D(sve_umulh_zpzz_d, uint64_t, do_umulh_d)
324 
325 DO_ZPZZ(sve_sdiv_zpzz_s, int32_t, H1_4, DO_SDIV)
326 DO_ZPZZ_D(sve_sdiv_zpzz_d, int64_t, DO_SDIV)
327 
328 DO_ZPZZ(sve_udiv_zpzz_s, uint32_t, H1_4, DO_UDIV)
329 DO_ZPZZ_D(sve_udiv_zpzz_d, uint64_t, DO_UDIV)
330 
331 /* Note that all bits of the shift are significant
332    and not modulo the element size.  */
333 #define DO_ASR(N, M)  (N >> MIN(M, sizeof(N) * 8 - 1))
334 #define DO_LSR(N, M)  (M < sizeof(N) * 8 ? N >> M : 0)
335 #define DO_LSL(N, M)  (M < sizeof(N) * 8 ? N << M : 0)
336 
337 DO_ZPZZ(sve_asr_zpzz_b, int8_t, H1, DO_ASR)
338 DO_ZPZZ(sve_lsr_zpzz_b, uint8_t, H1_2, DO_LSR)
339 DO_ZPZZ(sve_lsl_zpzz_b, uint8_t, H1_4, DO_LSL)
340 
341 DO_ZPZZ(sve_asr_zpzz_h, int16_t, H1, DO_ASR)
342 DO_ZPZZ(sve_lsr_zpzz_h, uint16_t, H1_2, DO_LSR)
343 DO_ZPZZ(sve_lsl_zpzz_h, uint16_t, H1_4, DO_LSL)
344 
345 DO_ZPZZ(sve_asr_zpzz_s, int32_t, H1, DO_ASR)
346 DO_ZPZZ(sve_lsr_zpzz_s, uint32_t, H1_2, DO_LSR)
347 DO_ZPZZ(sve_lsl_zpzz_s, uint32_t, H1_4, DO_LSL)
348 
349 DO_ZPZZ_D(sve_asr_zpzz_d, int64_t, DO_ASR)
350 DO_ZPZZ_D(sve_lsr_zpzz_d, uint64_t, DO_LSR)
351 DO_ZPZZ_D(sve_lsl_zpzz_d, uint64_t, DO_LSL)
352 
353 static inline uint16_t do_sadalp_h(int16_t n, int16_t m)
354 {
355     int8_t n1 = n, n2 = n >> 8;
356     return m + n1 + n2;
357 }
358 
359 static inline uint32_t do_sadalp_s(int32_t n, int32_t m)
360 {
361     int16_t n1 = n, n2 = n >> 16;
362     return m + n1 + n2;
363 }
364 
365 static inline uint64_t do_sadalp_d(int64_t n, int64_t m)
366 {
367     int32_t n1 = n, n2 = n >> 32;
368     return m + n1 + n2;
369 }
370 
371 DO_ZPZZ(sve2_sadalp_zpzz_h, int16_t, H1_2, do_sadalp_h)
372 DO_ZPZZ(sve2_sadalp_zpzz_s, int32_t, H1_4, do_sadalp_s)
373 DO_ZPZZ_D(sve2_sadalp_zpzz_d, int64_t, do_sadalp_d)
374 
375 static inline uint16_t do_uadalp_h(uint16_t n, uint16_t m)
376 {
377     uint8_t n1 = n, n2 = n >> 8;
378     return m + n1 + n2;
379 }
380 
381 static inline uint32_t do_uadalp_s(uint32_t n, uint32_t m)
382 {
383     uint16_t n1 = n, n2 = n >> 16;
384     return m + n1 + n2;
385 }
386 
387 static inline uint64_t do_uadalp_d(uint64_t n, uint64_t m)
388 {
389     uint32_t n1 = n, n2 = n >> 32;
390     return m + n1 + n2;
391 }
392 
393 DO_ZPZZ(sve2_uadalp_zpzz_h, uint16_t, H1_2, do_uadalp_h)
394 DO_ZPZZ(sve2_uadalp_zpzz_s, uint32_t, H1_4, do_uadalp_s)
395 DO_ZPZZ_D(sve2_uadalp_zpzz_d, uint64_t, do_uadalp_d)
396 
397 #define do_srshl_b(n, m)  do_sqrshl_bhs(n, m, 8, true, NULL)
398 #define do_srshl_h(n, m)  do_sqrshl_bhs(n, m, 16, true, NULL)
399 #define do_srshl_s(n, m)  do_sqrshl_bhs(n, m, 32, true, NULL)
400 #define do_srshl_d(n, m)  do_sqrshl_d(n, m, true, NULL)
401 
402 DO_ZPZZ(sve2_srshl_zpzz_b, int8_t, H1, do_srshl_b)
403 DO_ZPZZ(sve2_srshl_zpzz_h, int16_t, H1_2, do_srshl_h)
404 DO_ZPZZ(sve2_srshl_zpzz_s, int32_t, H1_4, do_srshl_s)
405 DO_ZPZZ_D(sve2_srshl_zpzz_d, int64_t, do_srshl_d)
406 
407 #define do_urshl_b(n, m)  do_uqrshl_bhs(n, (int8_t)m, 8, true, NULL)
408 #define do_urshl_h(n, m)  do_uqrshl_bhs(n, (int16_t)m, 16, true, NULL)
409 #define do_urshl_s(n, m)  do_uqrshl_bhs(n, m, 32, true, NULL)
410 #define do_urshl_d(n, m)  do_uqrshl_d(n, m, true, NULL)
411 
412 DO_ZPZZ(sve2_urshl_zpzz_b, uint8_t, H1, do_urshl_b)
413 DO_ZPZZ(sve2_urshl_zpzz_h, uint16_t, H1_2, do_urshl_h)
414 DO_ZPZZ(sve2_urshl_zpzz_s, uint32_t, H1_4, do_urshl_s)
415 DO_ZPZZ_D(sve2_urshl_zpzz_d, uint64_t, do_urshl_d)
416 
417 /*
418  * Unlike the NEON and AdvSIMD versions, there is no QC bit to set.
419  * We pass in a pointer to a dummy saturation field to trigger
420  * the saturating arithmetic but discard the information about
421  * whether it has occurred.
422  */
423 #define do_sqshl_b(n, m) \
424    ({ uint32_t discard; do_sqrshl_bhs(n, m, 8, false, &discard); })
425 #define do_sqshl_h(n, m) \
426    ({ uint32_t discard; do_sqrshl_bhs(n, m, 16, false, &discard); })
427 #define do_sqshl_s(n, m) \
428    ({ uint32_t discard; do_sqrshl_bhs(n, m, 32, false, &discard); })
429 #define do_sqshl_d(n, m) \
430    ({ uint32_t discard; do_sqrshl_d(n, m, false, &discard); })
431 
432 DO_ZPZZ(sve2_sqshl_zpzz_b, int8_t, H1_2, do_sqshl_b)
433 DO_ZPZZ(sve2_sqshl_zpzz_h, int16_t, H1_2, do_sqshl_h)
434 DO_ZPZZ(sve2_sqshl_zpzz_s, int32_t, H1_4, do_sqshl_s)
435 DO_ZPZZ_D(sve2_sqshl_zpzz_d, int64_t, do_sqshl_d)
436 
437 #define do_uqshl_b(n, m) \
438    ({ uint32_t discard; do_uqrshl_bhs(n, (int8_t)m, 8, false, &discard); })
439 #define do_uqshl_h(n, m) \
440    ({ uint32_t discard; do_uqrshl_bhs(n, (int16_t)m, 16, false, &discard); })
441 #define do_uqshl_s(n, m) \
442    ({ uint32_t discard; do_uqrshl_bhs(n, m, 32, false, &discard); })
443 #define do_uqshl_d(n, m) \
444    ({ uint32_t discard; do_uqrshl_d(n, m, false, &discard); })
445 
446 DO_ZPZZ(sve2_uqshl_zpzz_b, uint8_t, H1_2, do_uqshl_b)
447 DO_ZPZZ(sve2_uqshl_zpzz_h, uint16_t, H1_2, do_uqshl_h)
448 DO_ZPZZ(sve2_uqshl_zpzz_s, uint32_t, H1_4, do_uqshl_s)
449 DO_ZPZZ_D(sve2_uqshl_zpzz_d, uint64_t, do_uqshl_d)
450 
451 #define do_sqrshl_b(n, m) \
452    ({ uint32_t discard; do_sqrshl_bhs(n, m, 8, true, &discard); })
453 #define do_sqrshl_h(n, m) \
454    ({ uint32_t discard; do_sqrshl_bhs(n, m, 16, true, &discard); })
455 #define do_sqrshl_s(n, m) \
456    ({ uint32_t discard; do_sqrshl_bhs(n, m, 32, true, &discard); })
457 #define do_sqrshl_d(n, m) \
458    ({ uint32_t discard; do_sqrshl_d(n, m, true, &discard); })
459 
460 DO_ZPZZ(sve2_sqrshl_zpzz_b, int8_t, H1_2, do_sqrshl_b)
461 DO_ZPZZ(sve2_sqrshl_zpzz_h, int16_t, H1_2, do_sqrshl_h)
462 DO_ZPZZ(sve2_sqrshl_zpzz_s, int32_t, H1_4, do_sqrshl_s)
463 DO_ZPZZ_D(sve2_sqrshl_zpzz_d, int64_t, do_sqrshl_d)
464 
465 #undef do_sqrshl_d
466 
467 #define do_uqrshl_b(n, m) \
468    ({ uint32_t discard; do_uqrshl_bhs(n, (int8_t)m, 8, true, &discard); })
469 #define do_uqrshl_h(n, m) \
470    ({ uint32_t discard; do_uqrshl_bhs(n, (int16_t)m, 16, true, &discard); })
471 #define do_uqrshl_s(n, m) \
472    ({ uint32_t discard; do_uqrshl_bhs(n, m, 32, true, &discard); })
473 #define do_uqrshl_d(n, m) \
474    ({ uint32_t discard; do_uqrshl_d(n, m, true, &discard); })
475 
476 DO_ZPZZ(sve2_uqrshl_zpzz_b, uint8_t, H1_2, do_uqrshl_b)
477 DO_ZPZZ(sve2_uqrshl_zpzz_h, uint16_t, H1_2, do_uqrshl_h)
478 DO_ZPZZ(sve2_uqrshl_zpzz_s, uint32_t, H1_4, do_uqrshl_s)
479 DO_ZPZZ_D(sve2_uqrshl_zpzz_d, uint64_t, do_uqrshl_d)
480 
481 #undef do_uqrshl_d
482 
483 #define DO_HADD_BHS(n, m)  (((int64_t)n + m) >> 1)
484 #define DO_HADD_D(n, m)    ((n >> 1) + (m >> 1) + (n & m & 1))
485 
486 DO_ZPZZ(sve2_shadd_zpzz_b, int8_t, H1, DO_HADD_BHS)
487 DO_ZPZZ(sve2_shadd_zpzz_h, int16_t, H1_2, DO_HADD_BHS)
488 DO_ZPZZ(sve2_shadd_zpzz_s, int32_t, H1_4, DO_HADD_BHS)
489 DO_ZPZZ_D(sve2_shadd_zpzz_d, int64_t, DO_HADD_D)
490 
491 DO_ZPZZ(sve2_uhadd_zpzz_b, uint8_t, H1, DO_HADD_BHS)
492 DO_ZPZZ(sve2_uhadd_zpzz_h, uint16_t, H1_2, DO_HADD_BHS)
493 DO_ZPZZ(sve2_uhadd_zpzz_s, uint32_t, H1_4, DO_HADD_BHS)
494 DO_ZPZZ_D(sve2_uhadd_zpzz_d, uint64_t, DO_HADD_D)
495 
496 #define DO_RHADD_BHS(n, m)  (((int64_t)n + m + 1) >> 1)
497 #define DO_RHADD_D(n, m)    ((n >> 1) + (m >> 1) + ((n | m) & 1))
498 
499 DO_ZPZZ(sve2_srhadd_zpzz_b, int8_t, H1, DO_RHADD_BHS)
500 DO_ZPZZ(sve2_srhadd_zpzz_h, int16_t, H1_2, DO_RHADD_BHS)
501 DO_ZPZZ(sve2_srhadd_zpzz_s, int32_t, H1_4, DO_RHADD_BHS)
502 DO_ZPZZ_D(sve2_srhadd_zpzz_d, int64_t, DO_RHADD_D)
503 
504 DO_ZPZZ(sve2_urhadd_zpzz_b, uint8_t, H1, DO_RHADD_BHS)
505 DO_ZPZZ(sve2_urhadd_zpzz_h, uint16_t, H1_2, DO_RHADD_BHS)
506 DO_ZPZZ(sve2_urhadd_zpzz_s, uint32_t, H1_4, DO_RHADD_BHS)
507 DO_ZPZZ_D(sve2_urhadd_zpzz_d, uint64_t, DO_RHADD_D)
508 
509 #define DO_HSUB_BHS(n, m)  (((int64_t)n - m) >> 1)
510 #define DO_HSUB_D(n, m)    ((n >> 1) - (m >> 1) - (~n & m & 1))
511 
512 DO_ZPZZ(sve2_shsub_zpzz_b, int8_t, H1, DO_HSUB_BHS)
513 DO_ZPZZ(sve2_shsub_zpzz_h, int16_t, H1_2, DO_HSUB_BHS)
514 DO_ZPZZ(sve2_shsub_zpzz_s, int32_t, H1_4, DO_HSUB_BHS)
515 DO_ZPZZ_D(sve2_shsub_zpzz_d, int64_t, DO_HSUB_D)
516 
517 DO_ZPZZ(sve2_uhsub_zpzz_b, uint8_t, H1, DO_HSUB_BHS)
518 DO_ZPZZ(sve2_uhsub_zpzz_h, uint16_t, H1_2, DO_HSUB_BHS)
519 DO_ZPZZ(sve2_uhsub_zpzz_s, uint32_t, H1_4, DO_HSUB_BHS)
520 DO_ZPZZ_D(sve2_uhsub_zpzz_d, uint64_t, DO_HSUB_D)
521 
522 static inline int32_t do_sat_bhs(int64_t val, int64_t min, int64_t max)
523 {
524     return val >= max ? max : val <= min ? min : val;
525 }
526 
527 #define DO_SQADD_B(n, m) do_sat_bhs((int64_t)n + m, INT8_MIN, INT8_MAX)
528 #define DO_SQADD_H(n, m) do_sat_bhs((int64_t)n + m, INT16_MIN, INT16_MAX)
529 #define DO_SQADD_S(n, m) do_sat_bhs((int64_t)n + m, INT32_MIN, INT32_MAX)
530 
531 static inline int64_t do_sqadd_d(int64_t n, int64_t m)
532 {
533     int64_t r = n + m;
534     if (((r ^ n) & ~(n ^ m)) < 0) {
535         /* Signed overflow.  */
536         return r < 0 ? INT64_MAX : INT64_MIN;
537     }
538     return r;
539 }
540 
541 DO_ZPZZ(sve2_sqadd_zpzz_b, int8_t, H1, DO_SQADD_B)
542 DO_ZPZZ(sve2_sqadd_zpzz_h, int16_t, H1_2, DO_SQADD_H)
543 DO_ZPZZ(sve2_sqadd_zpzz_s, int32_t, H1_4, DO_SQADD_S)
544 DO_ZPZZ_D(sve2_sqadd_zpzz_d, int64_t, do_sqadd_d)
545 
546 #define DO_UQADD_B(n, m) do_sat_bhs((int64_t)n + m, 0, UINT8_MAX)
547 #define DO_UQADD_H(n, m) do_sat_bhs((int64_t)n + m, 0, UINT16_MAX)
548 #define DO_UQADD_S(n, m) do_sat_bhs((int64_t)n + m, 0, UINT32_MAX)
549 
550 static inline uint64_t do_uqadd_d(uint64_t n, uint64_t m)
551 {
552     uint64_t r = n + m;
553     return r < n ? UINT64_MAX : r;
554 }
555 
556 DO_ZPZZ(sve2_uqadd_zpzz_b, uint8_t, H1, DO_UQADD_B)
557 DO_ZPZZ(sve2_uqadd_zpzz_h, uint16_t, H1_2, DO_UQADD_H)
558 DO_ZPZZ(sve2_uqadd_zpzz_s, uint32_t, H1_4, DO_UQADD_S)
559 DO_ZPZZ_D(sve2_uqadd_zpzz_d, uint64_t, do_uqadd_d)
560 
561 #define DO_SQSUB_B(n, m) do_sat_bhs((int64_t)n - m, INT8_MIN, INT8_MAX)
562 #define DO_SQSUB_H(n, m) do_sat_bhs((int64_t)n - m, INT16_MIN, INT16_MAX)
563 #define DO_SQSUB_S(n, m) do_sat_bhs((int64_t)n - m, INT32_MIN, INT32_MAX)
564 
565 static inline int64_t do_sqsub_d(int64_t n, int64_t m)
566 {
567     int64_t r = n - m;
568     if (((r ^ n) & (n ^ m)) < 0) {
569         /* Signed overflow.  */
570         return r < 0 ? INT64_MAX : INT64_MIN;
571     }
572     return r;
573 }
574 
575 DO_ZPZZ(sve2_sqsub_zpzz_b, int8_t, H1, DO_SQSUB_B)
576 DO_ZPZZ(sve2_sqsub_zpzz_h, int16_t, H1_2, DO_SQSUB_H)
577 DO_ZPZZ(sve2_sqsub_zpzz_s, int32_t, H1_4, DO_SQSUB_S)
578 DO_ZPZZ_D(sve2_sqsub_zpzz_d, int64_t, do_sqsub_d)
579 
580 #define DO_UQSUB_B(n, m) do_sat_bhs((int64_t)n - m, 0, UINT8_MAX)
581 #define DO_UQSUB_H(n, m) do_sat_bhs((int64_t)n - m, 0, UINT16_MAX)
582 #define DO_UQSUB_S(n, m) do_sat_bhs((int64_t)n - m, 0, UINT32_MAX)
583 
584 static inline uint64_t do_uqsub_d(uint64_t n, uint64_t m)
585 {
586     return n > m ? n - m : 0;
587 }
588 
589 DO_ZPZZ(sve2_uqsub_zpzz_b, uint8_t, H1, DO_UQSUB_B)
590 DO_ZPZZ(sve2_uqsub_zpzz_h, uint16_t, H1_2, DO_UQSUB_H)
591 DO_ZPZZ(sve2_uqsub_zpzz_s, uint32_t, H1_4, DO_UQSUB_S)
592 DO_ZPZZ_D(sve2_uqsub_zpzz_d, uint64_t, do_uqsub_d)
593 
594 #define DO_SUQADD_B(n, m) \
595     do_sat_bhs((int64_t)(int8_t)n + m, INT8_MIN, INT8_MAX)
596 #define DO_SUQADD_H(n, m) \
597     do_sat_bhs((int64_t)(int16_t)n + m, INT16_MIN, INT16_MAX)
598 #define DO_SUQADD_S(n, m) \
599     do_sat_bhs((int64_t)(int32_t)n + m, INT32_MIN, INT32_MAX)
600 
601 static inline int64_t do_suqadd_d(int64_t n, uint64_t m)
602 {
603     uint64_t r = n + m;
604 
605     if (n < 0) {
606         /* Note that m - abs(n) cannot underflow. */
607         if (r > INT64_MAX) {
608             /* Result is either very large positive or negative. */
609             if (m > -n) {
610                 /* m > abs(n), so r is a very large positive. */
611                 return INT64_MAX;
612             }
613             /* Result is negative. */
614         }
615     } else {
616         /* Both inputs are positive: check for overflow.  */
617         if (r < m || r > INT64_MAX) {
618             return INT64_MAX;
619         }
620     }
621     return r;
622 }
623 
624 DO_ZPZZ(sve2_suqadd_zpzz_b, uint8_t, H1, DO_SUQADD_B)
625 DO_ZPZZ(sve2_suqadd_zpzz_h, uint16_t, H1_2, DO_SUQADD_H)
626 DO_ZPZZ(sve2_suqadd_zpzz_s, uint32_t, H1_4, DO_SUQADD_S)
627 DO_ZPZZ_D(sve2_suqadd_zpzz_d, uint64_t, do_suqadd_d)
628 
629 #define DO_USQADD_B(n, m) \
630     do_sat_bhs((int64_t)n + (int8_t)m, 0, UINT8_MAX)
631 #define DO_USQADD_H(n, m) \
632     do_sat_bhs((int64_t)n + (int16_t)m, 0, UINT16_MAX)
633 #define DO_USQADD_S(n, m) \
634     do_sat_bhs((int64_t)n + (int32_t)m, 0, UINT32_MAX)
635 
636 static inline uint64_t do_usqadd_d(uint64_t n, int64_t m)
637 {
638     uint64_t r = n + m;
639 
640     if (m < 0) {
641         return n < -m ? 0 : r;
642     }
643     return r < n ? UINT64_MAX : r;
644 }
645 
646 DO_ZPZZ(sve2_usqadd_zpzz_b, uint8_t, H1, DO_USQADD_B)
647 DO_ZPZZ(sve2_usqadd_zpzz_h, uint16_t, H1_2, DO_USQADD_H)
648 DO_ZPZZ(sve2_usqadd_zpzz_s, uint32_t, H1_4, DO_USQADD_S)
649 DO_ZPZZ_D(sve2_usqadd_zpzz_d, uint64_t, do_usqadd_d)
650 
651 #undef DO_ZPZZ
652 #undef DO_ZPZZ_D
653 
654 /*
655  * Three operand expander, operating on element pairs.
656  * If the slot I is even, the elements from from VN {I, I+1}.
657  * If the slot I is odd, the elements from from VM {I-1, I}.
658  * Load all of the input elements in each pair before overwriting output.
659  */
660 #define DO_ZPZZ_PAIR(NAME, TYPE, H, OP) \
661 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
662 {                                                               \
663     intptr_t i, opr_sz = simd_oprsz(desc);                      \
664     for (i = 0; i < opr_sz; ) {                                 \
665         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));         \
666         do {                                                    \
667             TYPE n0 = *(TYPE *)(vn + H(i));                     \
668             TYPE m0 = *(TYPE *)(vm + H(i));                     \
669             TYPE n1 = *(TYPE *)(vn + H(i + sizeof(TYPE)));      \
670             TYPE m1 = *(TYPE *)(vm + H(i + sizeof(TYPE)));      \
671             if (pg & 1) {                                       \
672                 *(TYPE *)(vd + H(i)) = OP(n0, n1);              \
673             }                                                   \
674             i += sizeof(TYPE), pg >>= sizeof(TYPE);             \
675             if (pg & 1) {                                       \
676                 *(TYPE *)(vd + H(i)) = OP(m0, m1);              \
677             }                                                   \
678             i += sizeof(TYPE), pg >>= sizeof(TYPE);             \
679         } while (i & 15);                                       \
680     }                                                           \
681 }
682 
683 /* Similarly, specialized for 64-bit operands.  */
684 #define DO_ZPZZ_PAIR_D(NAME, TYPE, OP) \
685 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
686 {                                                               \
687     intptr_t i, opr_sz = simd_oprsz(desc) / 8;                  \
688     TYPE *d = vd, *n = vn, *m = vm;                             \
689     uint8_t *pg = vg;                                           \
690     for (i = 0; i < opr_sz; i += 2) {                           \
691         TYPE n0 = n[i], n1 = n[i + 1];                          \
692         TYPE m0 = m[i], m1 = m[i + 1];                          \
693         if (pg[H1(i)] & 1) {                                    \
694             d[i] = OP(n0, n1);                                  \
695         }                                                       \
696         if (pg[H1(i + 1)] & 1) {                                \
697             d[i + 1] = OP(m0, m1);                              \
698         }                                                       \
699     }                                                           \
700 }
701 
702 DO_ZPZZ_PAIR(sve2_addp_zpzz_b, uint8_t, H1, DO_ADD)
703 DO_ZPZZ_PAIR(sve2_addp_zpzz_h, uint16_t, H1_2, DO_ADD)
704 DO_ZPZZ_PAIR(sve2_addp_zpzz_s, uint32_t, H1_4, DO_ADD)
705 DO_ZPZZ_PAIR_D(sve2_addp_zpzz_d, uint64_t, DO_ADD)
706 
707 DO_ZPZZ_PAIR(sve2_umaxp_zpzz_b, uint8_t, H1, DO_MAX)
708 DO_ZPZZ_PAIR(sve2_umaxp_zpzz_h, uint16_t, H1_2, DO_MAX)
709 DO_ZPZZ_PAIR(sve2_umaxp_zpzz_s, uint32_t, H1_4, DO_MAX)
710 DO_ZPZZ_PAIR_D(sve2_umaxp_zpzz_d, uint64_t, DO_MAX)
711 
712 DO_ZPZZ_PAIR(sve2_uminp_zpzz_b, uint8_t, H1, DO_MIN)
713 DO_ZPZZ_PAIR(sve2_uminp_zpzz_h, uint16_t, H1_2, DO_MIN)
714 DO_ZPZZ_PAIR(sve2_uminp_zpzz_s, uint32_t, H1_4, DO_MIN)
715 DO_ZPZZ_PAIR_D(sve2_uminp_zpzz_d, uint64_t, DO_MIN)
716 
717 DO_ZPZZ_PAIR(sve2_smaxp_zpzz_b, int8_t, H1, DO_MAX)
718 DO_ZPZZ_PAIR(sve2_smaxp_zpzz_h, int16_t, H1_2, DO_MAX)
719 DO_ZPZZ_PAIR(sve2_smaxp_zpzz_s, int32_t, H1_4, DO_MAX)
720 DO_ZPZZ_PAIR_D(sve2_smaxp_zpzz_d, int64_t, DO_MAX)
721 
722 DO_ZPZZ_PAIR(sve2_sminp_zpzz_b, int8_t, H1, DO_MIN)
723 DO_ZPZZ_PAIR(sve2_sminp_zpzz_h, int16_t, H1_2, DO_MIN)
724 DO_ZPZZ_PAIR(sve2_sminp_zpzz_s, int32_t, H1_4, DO_MIN)
725 DO_ZPZZ_PAIR_D(sve2_sminp_zpzz_d, int64_t, DO_MIN)
726 
727 #undef DO_ZPZZ_PAIR
728 #undef DO_ZPZZ_PAIR_D
729 
730 #define DO_ZPZZ_PAIR_FP(NAME, TYPE, H, OP)                              \
731 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg,               \
732                   void *status, uint32_t desc)                          \
733 {                                                                       \
734     intptr_t i, opr_sz = simd_oprsz(desc);                              \
735     for (i = 0; i < opr_sz; ) {                                         \
736         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));                 \
737         do {                                                            \
738             TYPE n0 = *(TYPE *)(vn + H(i));                             \
739             TYPE m0 = *(TYPE *)(vm + H(i));                             \
740             TYPE n1 = *(TYPE *)(vn + H(i + sizeof(TYPE)));              \
741             TYPE m1 = *(TYPE *)(vm + H(i + sizeof(TYPE)));              \
742             if (pg & 1) {                                               \
743                 *(TYPE *)(vd + H(i)) = OP(n0, n1, status);              \
744             }                                                           \
745             i += sizeof(TYPE), pg >>= sizeof(TYPE);                     \
746             if (pg & 1) {                                               \
747                 *(TYPE *)(vd + H(i)) = OP(m0, m1, status);              \
748             }                                                           \
749             i += sizeof(TYPE), pg >>= sizeof(TYPE);                     \
750         } while (i & 15);                                               \
751     }                                                                   \
752 }
753 
754 DO_ZPZZ_PAIR_FP(sve2_faddp_zpzz_h, float16, H1_2, float16_add)
755 DO_ZPZZ_PAIR_FP(sve2_faddp_zpzz_s, float32, H1_4, float32_add)
756 DO_ZPZZ_PAIR_FP(sve2_faddp_zpzz_d, float64, H1_8, float64_add)
757 
758 DO_ZPZZ_PAIR_FP(sve2_fmaxnmp_zpzz_h, float16, H1_2, float16_maxnum)
759 DO_ZPZZ_PAIR_FP(sve2_fmaxnmp_zpzz_s, float32, H1_4, float32_maxnum)
760 DO_ZPZZ_PAIR_FP(sve2_fmaxnmp_zpzz_d, float64, H1_8, float64_maxnum)
761 
762 DO_ZPZZ_PAIR_FP(sve2_fminnmp_zpzz_h, float16, H1_2, float16_minnum)
763 DO_ZPZZ_PAIR_FP(sve2_fminnmp_zpzz_s, float32, H1_4, float32_minnum)
764 DO_ZPZZ_PAIR_FP(sve2_fminnmp_zpzz_d, float64, H1_8, float64_minnum)
765 
766 DO_ZPZZ_PAIR_FP(sve2_fmaxp_zpzz_h, float16, H1_2, float16_max)
767 DO_ZPZZ_PAIR_FP(sve2_fmaxp_zpzz_s, float32, H1_4, float32_max)
768 DO_ZPZZ_PAIR_FP(sve2_fmaxp_zpzz_d, float64, H1_8, float64_max)
769 
770 DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_h, float16, H1_2, float16_min)
771 DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_s, float32, H1_4, float32_min)
772 DO_ZPZZ_PAIR_FP(sve2_fminp_zpzz_d, float64, H1_8, float64_min)
773 
774 #undef DO_ZPZZ_PAIR_FP
775 
776 /* Three-operand expander, controlled by a predicate, in which the
777  * third operand is "wide".  That is, for D = N op M, the same 64-bit
778  * value of M is used with all of the narrower values of N.
779  */
780 #define DO_ZPZW(NAME, TYPE, TYPEW, H, OP)                               \
781 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
782 {                                                                       \
783     intptr_t i, opr_sz = simd_oprsz(desc);                              \
784     for (i = 0; i < opr_sz; ) {                                         \
785         uint8_t pg = *(uint8_t *)(vg + H1(i >> 3));                     \
786         TYPEW mm = *(TYPEW *)(vm + i);                                  \
787         do {                                                            \
788             if (pg & 1) {                                               \
789                 TYPE nn = *(TYPE *)(vn + H(i));                         \
790                 *(TYPE *)(vd + H(i)) = OP(nn, mm);                      \
791             }                                                           \
792             i += sizeof(TYPE), pg >>= sizeof(TYPE);                     \
793         } while (i & 7);                                                \
794     }                                                                   \
795 }
796 
797 DO_ZPZW(sve_asr_zpzw_b, int8_t, uint64_t, H1, DO_ASR)
798 DO_ZPZW(sve_lsr_zpzw_b, uint8_t, uint64_t, H1, DO_LSR)
799 DO_ZPZW(sve_lsl_zpzw_b, uint8_t, uint64_t, H1, DO_LSL)
800 
801 DO_ZPZW(sve_asr_zpzw_h, int16_t, uint64_t, H1_2, DO_ASR)
802 DO_ZPZW(sve_lsr_zpzw_h, uint16_t, uint64_t, H1_2, DO_LSR)
803 DO_ZPZW(sve_lsl_zpzw_h, uint16_t, uint64_t, H1_2, DO_LSL)
804 
805 DO_ZPZW(sve_asr_zpzw_s, int32_t, uint64_t, H1_4, DO_ASR)
806 DO_ZPZW(sve_lsr_zpzw_s, uint32_t, uint64_t, H1_4, DO_LSR)
807 DO_ZPZW(sve_lsl_zpzw_s, uint32_t, uint64_t, H1_4, DO_LSL)
808 
809 #undef DO_ZPZW
810 
811 /* Fully general two-operand expander, controlled by a predicate.
812  */
813 #define DO_ZPZ(NAME, TYPE, H, OP)                               \
814 void HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc)  \
815 {                                                               \
816     intptr_t i, opr_sz = simd_oprsz(desc);                      \
817     for (i = 0; i < opr_sz; ) {                                 \
818         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));         \
819         do {                                                    \
820             if (pg & 1) {                                       \
821                 TYPE nn = *(TYPE *)(vn + H(i));                 \
822                 *(TYPE *)(vd + H(i)) = OP(nn);                  \
823             }                                                   \
824             i += sizeof(TYPE), pg >>= sizeof(TYPE);             \
825         } while (i & 15);                                       \
826     }                                                           \
827 }
828 
829 /* Similarly, specialized for 64-bit operands.  */
830 #define DO_ZPZ_D(NAME, TYPE, OP)                                \
831 void HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc)  \
832 {                                                               \
833     intptr_t i, opr_sz = simd_oprsz(desc) / 8;                  \
834     TYPE *d = vd, *n = vn;                                      \
835     uint8_t *pg = vg;                                           \
836     for (i = 0; i < opr_sz; i += 1) {                           \
837         if (pg[H1(i)] & 1) {                                    \
838             TYPE nn = n[i];                                     \
839             d[i] = OP(nn);                                      \
840         }                                                       \
841     }                                                           \
842 }
843 
844 #define DO_CLS_B(N)   (clrsb32(N) - 24)
845 #define DO_CLS_H(N)   (clrsb32(N) - 16)
846 
847 DO_ZPZ(sve_cls_b, int8_t, H1, DO_CLS_B)
848 DO_ZPZ(sve_cls_h, int16_t, H1_2, DO_CLS_H)
849 DO_ZPZ(sve_cls_s, int32_t, H1_4, clrsb32)
850 DO_ZPZ_D(sve_cls_d, int64_t, clrsb64)
851 
852 #define DO_CLZ_B(N)   (clz32(N) - 24)
853 #define DO_CLZ_H(N)   (clz32(N) - 16)
854 
855 DO_ZPZ(sve_clz_b, uint8_t, H1, DO_CLZ_B)
856 DO_ZPZ(sve_clz_h, uint16_t, H1_2, DO_CLZ_H)
857 DO_ZPZ(sve_clz_s, uint32_t, H1_4, clz32)
858 DO_ZPZ_D(sve_clz_d, uint64_t, clz64)
859 
860 DO_ZPZ(sve_cnt_zpz_b, uint8_t, H1, ctpop8)
861 DO_ZPZ(sve_cnt_zpz_h, uint16_t, H1_2, ctpop16)
862 DO_ZPZ(sve_cnt_zpz_s, uint32_t, H1_4, ctpop32)
863 DO_ZPZ_D(sve_cnt_zpz_d, uint64_t, ctpop64)
864 
865 #define DO_CNOT(N)    (N == 0)
866 
867 DO_ZPZ(sve_cnot_b, uint8_t, H1, DO_CNOT)
868 DO_ZPZ(sve_cnot_h, uint16_t, H1_2, DO_CNOT)
869 DO_ZPZ(sve_cnot_s, uint32_t, H1_4, DO_CNOT)
870 DO_ZPZ_D(sve_cnot_d, uint64_t, DO_CNOT)
871 
872 #define DO_FABS(N)    (N & ((__typeof(N))-1 >> 1))
873 
874 DO_ZPZ(sve_fabs_h, uint16_t, H1_2, DO_FABS)
875 DO_ZPZ(sve_fabs_s, uint32_t, H1_4, DO_FABS)
876 DO_ZPZ_D(sve_fabs_d, uint64_t, DO_FABS)
877 
878 #define DO_FNEG(N)    (N ^ ~((__typeof(N))-1 >> 1))
879 
880 DO_ZPZ(sve_fneg_h, uint16_t, H1_2, DO_FNEG)
881 DO_ZPZ(sve_fneg_s, uint32_t, H1_4, DO_FNEG)
882 DO_ZPZ_D(sve_fneg_d, uint64_t, DO_FNEG)
883 
884 #define DO_NOT(N)    (~N)
885 
886 DO_ZPZ(sve_not_zpz_b, uint8_t, H1, DO_NOT)
887 DO_ZPZ(sve_not_zpz_h, uint16_t, H1_2, DO_NOT)
888 DO_ZPZ(sve_not_zpz_s, uint32_t, H1_4, DO_NOT)
889 DO_ZPZ_D(sve_not_zpz_d, uint64_t, DO_NOT)
890 
891 #define DO_SXTB(N)    ((int8_t)N)
892 #define DO_SXTH(N)    ((int16_t)N)
893 #define DO_SXTS(N)    ((int32_t)N)
894 #define DO_UXTB(N)    ((uint8_t)N)
895 #define DO_UXTH(N)    ((uint16_t)N)
896 #define DO_UXTS(N)    ((uint32_t)N)
897 
898 DO_ZPZ(sve_sxtb_h, uint16_t, H1_2, DO_SXTB)
899 DO_ZPZ(sve_sxtb_s, uint32_t, H1_4, DO_SXTB)
900 DO_ZPZ(sve_sxth_s, uint32_t, H1_4, DO_SXTH)
901 DO_ZPZ_D(sve_sxtb_d, uint64_t, DO_SXTB)
902 DO_ZPZ_D(sve_sxth_d, uint64_t, DO_SXTH)
903 DO_ZPZ_D(sve_sxtw_d, uint64_t, DO_SXTS)
904 
905 DO_ZPZ(sve_uxtb_h, uint16_t, H1_2, DO_UXTB)
906 DO_ZPZ(sve_uxtb_s, uint32_t, H1_4, DO_UXTB)
907 DO_ZPZ(sve_uxth_s, uint32_t, H1_4, DO_UXTH)
908 DO_ZPZ_D(sve_uxtb_d, uint64_t, DO_UXTB)
909 DO_ZPZ_D(sve_uxth_d, uint64_t, DO_UXTH)
910 DO_ZPZ_D(sve_uxtw_d, uint64_t, DO_UXTS)
911 
912 #define DO_ABS(N)    (N < 0 ? -N : N)
913 
914 DO_ZPZ(sve_abs_b, int8_t, H1, DO_ABS)
915 DO_ZPZ(sve_abs_h, int16_t, H1_2, DO_ABS)
916 DO_ZPZ(sve_abs_s, int32_t, H1_4, DO_ABS)
917 DO_ZPZ_D(sve_abs_d, int64_t, DO_ABS)
918 
919 #define DO_NEG(N)    (-N)
920 
921 DO_ZPZ(sve_neg_b, uint8_t, H1, DO_NEG)
922 DO_ZPZ(sve_neg_h, uint16_t, H1_2, DO_NEG)
923 DO_ZPZ(sve_neg_s, uint32_t, H1_4, DO_NEG)
924 DO_ZPZ_D(sve_neg_d, uint64_t, DO_NEG)
925 
926 DO_ZPZ(sve_revb_h, uint16_t, H1_2, bswap16)
927 DO_ZPZ(sve_revb_s, uint32_t, H1_4, bswap32)
928 DO_ZPZ_D(sve_revb_d, uint64_t, bswap64)
929 
930 DO_ZPZ(sve_revh_s, uint32_t, H1_4, hswap32)
931 DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
932 
933 DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
934 
935 void HELPER(sme_revd_q)(void *vd, void *vn, void *vg, uint32_t desc)
936 {
937     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
938     uint64_t *d = vd, *n = vn;
939     uint8_t *pg = vg;
940 
941     for (i = 0; i < opr_sz; i += 2) {
942         if (pg[H1(i)] & 1) {
943             uint64_t n0 = n[i + 0];
944             uint64_t n1 = n[i + 1];
945             d[i + 0] = n1;
946             d[i + 1] = n0;
947         }
948     }
949 }
950 
951 DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
952 DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
953 DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
954 DO_ZPZ_D(sve_rbit_d, uint64_t, revbit64)
955 
956 #define DO_SQABS(X) \
957     ({ __typeof(X) x_ = (X), min_ = 1ull << (sizeof(X) * 8 - 1); \
958        x_ >= 0 ? x_ : x_ == min_ ? -min_ - 1 : -x_; })
959 
960 DO_ZPZ(sve2_sqabs_b, int8_t, H1, DO_SQABS)
961 DO_ZPZ(sve2_sqabs_h, int16_t, H1_2, DO_SQABS)
962 DO_ZPZ(sve2_sqabs_s, int32_t, H1_4, DO_SQABS)
963 DO_ZPZ_D(sve2_sqabs_d, int64_t, DO_SQABS)
964 
965 #define DO_SQNEG(X) \
966     ({ __typeof(X) x_ = (X), min_ = 1ull << (sizeof(X) * 8 - 1); \
967        x_ == min_ ? -min_ - 1 : -x_; })
968 
969 DO_ZPZ(sve2_sqneg_b, uint8_t, H1, DO_SQNEG)
970 DO_ZPZ(sve2_sqneg_h, uint16_t, H1_2, DO_SQNEG)
971 DO_ZPZ(sve2_sqneg_s, uint32_t, H1_4, DO_SQNEG)
972 DO_ZPZ_D(sve2_sqneg_d, uint64_t, DO_SQNEG)
973 
974 DO_ZPZ(sve2_urecpe_s, uint32_t, H1_4, helper_recpe_u32)
975 DO_ZPZ(sve2_ursqrte_s, uint32_t, H1_4, helper_rsqrte_u32)
976 
977 /* Three-operand expander, unpredicated, in which the third operand is "wide".
978  */
979 #define DO_ZZW(NAME, TYPE, TYPEW, H, OP)                       \
980 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
981 {                                                              \
982     intptr_t i, opr_sz = simd_oprsz(desc);                     \
983     for (i = 0; i < opr_sz; ) {                                \
984         TYPEW mm = *(TYPEW *)(vm + i);                         \
985         do {                                                   \
986             TYPE nn = *(TYPE *)(vn + H(i));                    \
987             *(TYPE *)(vd + H(i)) = OP(nn, mm);                 \
988             i += sizeof(TYPE);                                 \
989         } while (i & 7);                                       \
990     }                                                          \
991 }
992 
993 DO_ZZW(sve_asr_zzw_b, int8_t, uint64_t, H1, DO_ASR)
994 DO_ZZW(sve_lsr_zzw_b, uint8_t, uint64_t, H1, DO_LSR)
995 DO_ZZW(sve_lsl_zzw_b, uint8_t, uint64_t, H1, DO_LSL)
996 
997 DO_ZZW(sve_asr_zzw_h, int16_t, uint64_t, H1_2, DO_ASR)
998 DO_ZZW(sve_lsr_zzw_h, uint16_t, uint64_t, H1_2, DO_LSR)
999 DO_ZZW(sve_lsl_zzw_h, uint16_t, uint64_t, H1_2, DO_LSL)
1000 
1001 DO_ZZW(sve_asr_zzw_s, int32_t, uint64_t, H1_4, DO_ASR)
1002 DO_ZZW(sve_lsr_zzw_s, uint32_t, uint64_t, H1_4, DO_LSR)
1003 DO_ZZW(sve_lsl_zzw_s, uint32_t, uint64_t, H1_4, DO_LSL)
1004 
1005 #undef DO_ZZW
1006 
1007 #undef DO_CLS_B
1008 #undef DO_CLS_H
1009 #undef DO_CLZ_B
1010 #undef DO_CLZ_H
1011 #undef DO_CNOT
1012 #undef DO_FABS
1013 #undef DO_FNEG
1014 #undef DO_ABS
1015 #undef DO_NEG
1016 #undef DO_ZPZ
1017 #undef DO_ZPZ_D
1018 
1019 /*
1020  * Three-operand expander, unpredicated, in which the two inputs are
1021  * selected from the top or bottom half of the wide column.
1022  */
1023 #define DO_ZZZ_TB(NAME, TYPEW, TYPEN, HW, HN, OP) \
1024 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)          \
1025 {                                                                       \
1026     intptr_t i, opr_sz = simd_oprsz(desc);                              \
1027     int sel1 = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPEN);     \
1028     int sel2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1) * sizeof(TYPEN); \
1029     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {                       \
1030         TYPEW nn = *(TYPEN *)(vn + HN(i + sel1));                       \
1031         TYPEW mm = *(TYPEN *)(vm + HN(i + sel2));                       \
1032         *(TYPEW *)(vd + HW(i)) = OP(nn, mm);                            \
1033     }                                                                   \
1034 }
1035 
1036 DO_ZZZ_TB(sve2_saddl_h, int16_t, int8_t, H1_2, H1, DO_ADD)
1037 DO_ZZZ_TB(sve2_saddl_s, int32_t, int16_t, H1_4, H1_2, DO_ADD)
1038 DO_ZZZ_TB(sve2_saddl_d, int64_t, int32_t, H1_8, H1_4, DO_ADD)
1039 
1040 DO_ZZZ_TB(sve2_ssubl_h, int16_t, int8_t, H1_2, H1, DO_SUB)
1041 DO_ZZZ_TB(sve2_ssubl_s, int32_t, int16_t, H1_4, H1_2, DO_SUB)
1042 DO_ZZZ_TB(sve2_ssubl_d, int64_t, int32_t, H1_8, H1_4, DO_SUB)
1043 
1044 DO_ZZZ_TB(sve2_sabdl_h, int16_t, int8_t, H1_2, H1, DO_ABD)
1045 DO_ZZZ_TB(sve2_sabdl_s, int32_t, int16_t, H1_4, H1_2, DO_ABD)
1046 DO_ZZZ_TB(sve2_sabdl_d, int64_t, int32_t, H1_8, H1_4, DO_ABD)
1047 
1048 DO_ZZZ_TB(sve2_uaddl_h, uint16_t, uint8_t, H1_2, H1, DO_ADD)
1049 DO_ZZZ_TB(sve2_uaddl_s, uint32_t, uint16_t, H1_4, H1_2, DO_ADD)
1050 DO_ZZZ_TB(sve2_uaddl_d, uint64_t, uint32_t, H1_8, H1_4, DO_ADD)
1051 
1052 DO_ZZZ_TB(sve2_usubl_h, uint16_t, uint8_t, H1_2, H1, DO_SUB)
1053 DO_ZZZ_TB(sve2_usubl_s, uint32_t, uint16_t, H1_4, H1_2, DO_SUB)
1054 DO_ZZZ_TB(sve2_usubl_d, uint64_t, uint32_t, H1_8, H1_4, DO_SUB)
1055 
1056 DO_ZZZ_TB(sve2_uabdl_h, uint16_t, uint8_t, H1_2, H1, DO_ABD)
1057 DO_ZZZ_TB(sve2_uabdl_s, uint32_t, uint16_t, H1_4, H1_2, DO_ABD)
1058 DO_ZZZ_TB(sve2_uabdl_d, uint64_t, uint32_t, H1_8, H1_4, DO_ABD)
1059 
1060 DO_ZZZ_TB(sve2_smull_zzz_h, int16_t, int8_t, H1_2, H1, DO_MUL)
1061 DO_ZZZ_TB(sve2_smull_zzz_s, int32_t, int16_t, H1_4, H1_2, DO_MUL)
1062 DO_ZZZ_TB(sve2_smull_zzz_d, int64_t, int32_t, H1_8, H1_4, DO_MUL)
1063 
1064 DO_ZZZ_TB(sve2_umull_zzz_h, uint16_t, uint8_t, H1_2, H1, DO_MUL)
1065 DO_ZZZ_TB(sve2_umull_zzz_s, uint32_t, uint16_t, H1_4, H1_2, DO_MUL)
1066 DO_ZZZ_TB(sve2_umull_zzz_d, uint64_t, uint32_t, H1_8, H1_4, DO_MUL)
1067 
1068 /* Note that the multiply cannot overflow, but the doubling can. */
1069 static inline int16_t do_sqdmull_h(int16_t n, int16_t m)
1070 {
1071     int16_t val = n * m;
1072     return DO_SQADD_H(val, val);
1073 }
1074 
1075 static inline int32_t do_sqdmull_s(int32_t n, int32_t m)
1076 {
1077     int32_t val = n * m;
1078     return DO_SQADD_S(val, val);
1079 }
1080 
1081 static inline int64_t do_sqdmull_d(int64_t n, int64_t m)
1082 {
1083     int64_t val = n * m;
1084     return do_sqadd_d(val, val);
1085 }
1086 
1087 DO_ZZZ_TB(sve2_sqdmull_zzz_h, int16_t, int8_t, H1_2, H1, do_sqdmull_h)
1088 DO_ZZZ_TB(sve2_sqdmull_zzz_s, int32_t, int16_t, H1_4, H1_2, do_sqdmull_s)
1089 DO_ZZZ_TB(sve2_sqdmull_zzz_d, int64_t, int32_t, H1_8, H1_4, do_sqdmull_d)
1090 
1091 #undef DO_ZZZ_TB
1092 
1093 #define DO_ZZZ_WTB(NAME, TYPEW, TYPEN, HW, HN, OP) \
1094 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
1095 {                                                              \
1096     intptr_t i, opr_sz = simd_oprsz(desc);                     \
1097     int sel2 = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPEN); \
1098     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {              \
1099         TYPEW nn = *(TYPEW *)(vn + HW(i));                     \
1100         TYPEW mm = *(TYPEN *)(vm + HN(i + sel2));              \
1101         *(TYPEW *)(vd + HW(i)) = OP(nn, mm);                   \
1102     }                                                          \
1103 }
1104 
1105 DO_ZZZ_WTB(sve2_saddw_h, int16_t, int8_t, H1_2, H1, DO_ADD)
1106 DO_ZZZ_WTB(sve2_saddw_s, int32_t, int16_t, H1_4, H1_2, DO_ADD)
1107 DO_ZZZ_WTB(sve2_saddw_d, int64_t, int32_t, H1_8, H1_4, DO_ADD)
1108 
1109 DO_ZZZ_WTB(sve2_ssubw_h, int16_t, int8_t, H1_2, H1, DO_SUB)
1110 DO_ZZZ_WTB(sve2_ssubw_s, int32_t, int16_t, H1_4, H1_2, DO_SUB)
1111 DO_ZZZ_WTB(sve2_ssubw_d, int64_t, int32_t, H1_8, H1_4, DO_SUB)
1112 
1113 DO_ZZZ_WTB(sve2_uaddw_h, uint16_t, uint8_t, H1_2, H1, DO_ADD)
1114 DO_ZZZ_WTB(sve2_uaddw_s, uint32_t, uint16_t, H1_4, H1_2, DO_ADD)
1115 DO_ZZZ_WTB(sve2_uaddw_d, uint64_t, uint32_t, H1_8, H1_4, DO_ADD)
1116 
1117 DO_ZZZ_WTB(sve2_usubw_h, uint16_t, uint8_t, H1_2, H1, DO_SUB)
1118 DO_ZZZ_WTB(sve2_usubw_s, uint32_t, uint16_t, H1_4, H1_2, DO_SUB)
1119 DO_ZZZ_WTB(sve2_usubw_d, uint64_t, uint32_t, H1_8, H1_4, DO_SUB)
1120 
1121 #undef DO_ZZZ_WTB
1122 
1123 #define DO_ZZZ_NTB(NAME, TYPE, H, OP)                                   \
1124 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)          \
1125 {                                                                       \
1126     intptr_t i, opr_sz = simd_oprsz(desc);                              \
1127     intptr_t sel1 = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPE); \
1128     intptr_t sel2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1) * sizeof(TYPE); \
1129     for (i = 0; i < opr_sz; i += 2 * sizeof(TYPE)) {                    \
1130         TYPE nn = *(TYPE *)(vn + H(i + sel1));                          \
1131         TYPE mm = *(TYPE *)(vm + H(i + sel2));                          \
1132         *(TYPE *)(vd + H(i + sel1)) = OP(nn, mm);                       \
1133     }                                                                   \
1134 }
1135 
1136 DO_ZZZ_NTB(sve2_eoril_b, uint8_t, H1, DO_EOR)
1137 DO_ZZZ_NTB(sve2_eoril_h, uint16_t, H1_2, DO_EOR)
1138 DO_ZZZ_NTB(sve2_eoril_s, uint32_t, H1_4, DO_EOR)
1139 DO_ZZZ_NTB(sve2_eoril_d, uint64_t, H1_8, DO_EOR)
1140 
1141 #undef DO_ZZZ_NTB
1142 
1143 #define DO_ZZZW_ACC(NAME, TYPEW, TYPEN, HW, HN, OP) \
1144 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
1145 {                                                               \
1146     intptr_t i, opr_sz = simd_oprsz(desc);                      \
1147     intptr_t sel1 = simd_data(desc) * sizeof(TYPEN);            \
1148     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {               \
1149         TYPEW nn = *(TYPEN *)(vn + HN(i + sel1));               \
1150         TYPEW mm = *(TYPEN *)(vm + HN(i + sel1));               \
1151         TYPEW aa = *(TYPEW *)(va + HW(i));                      \
1152         *(TYPEW *)(vd + HW(i)) = OP(nn, mm) + aa;               \
1153     }                                                           \
1154 }
1155 
1156 DO_ZZZW_ACC(sve2_sabal_h, int16_t, int8_t, H1_2, H1, DO_ABD)
1157 DO_ZZZW_ACC(sve2_sabal_s, int32_t, int16_t, H1_4, H1_2, DO_ABD)
1158 DO_ZZZW_ACC(sve2_sabal_d, int64_t, int32_t, H1_8, H1_4, DO_ABD)
1159 
1160 DO_ZZZW_ACC(sve2_uabal_h, uint16_t, uint8_t, H1_2, H1, DO_ABD)
1161 DO_ZZZW_ACC(sve2_uabal_s, uint32_t, uint16_t, H1_4, H1_2, DO_ABD)
1162 DO_ZZZW_ACC(sve2_uabal_d, uint64_t, uint32_t, H1_8, H1_4, DO_ABD)
1163 
1164 DO_ZZZW_ACC(sve2_smlal_zzzw_h, int16_t, int8_t, H1_2, H1, DO_MUL)
1165 DO_ZZZW_ACC(sve2_smlal_zzzw_s, int32_t, int16_t, H1_4, H1_2, DO_MUL)
1166 DO_ZZZW_ACC(sve2_smlal_zzzw_d, int64_t, int32_t, H1_8, H1_4, DO_MUL)
1167 
1168 DO_ZZZW_ACC(sve2_umlal_zzzw_h, uint16_t, uint8_t, H1_2, H1, DO_MUL)
1169 DO_ZZZW_ACC(sve2_umlal_zzzw_s, uint32_t, uint16_t, H1_4, H1_2, DO_MUL)
1170 DO_ZZZW_ACC(sve2_umlal_zzzw_d, uint64_t, uint32_t, H1_8, H1_4, DO_MUL)
1171 
1172 #define DO_NMUL(N, M)  -(N * M)
1173 
1174 DO_ZZZW_ACC(sve2_smlsl_zzzw_h, int16_t, int8_t, H1_2, H1, DO_NMUL)
1175 DO_ZZZW_ACC(sve2_smlsl_zzzw_s, int32_t, int16_t, H1_4, H1_2, DO_NMUL)
1176 DO_ZZZW_ACC(sve2_smlsl_zzzw_d, int64_t, int32_t, H1_8, H1_4, DO_NMUL)
1177 
1178 DO_ZZZW_ACC(sve2_umlsl_zzzw_h, uint16_t, uint8_t, H1_2, H1, DO_NMUL)
1179 DO_ZZZW_ACC(sve2_umlsl_zzzw_s, uint32_t, uint16_t, H1_4, H1_2, DO_NMUL)
1180 DO_ZZZW_ACC(sve2_umlsl_zzzw_d, uint64_t, uint32_t, H1_8, H1_4, DO_NMUL)
1181 
1182 #undef DO_ZZZW_ACC
1183 
1184 #define DO_XTNB(NAME, TYPE, OP) \
1185 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)         \
1186 {                                                            \
1187     intptr_t i, opr_sz = simd_oprsz(desc);                   \
1188     for (i = 0; i < opr_sz; i += sizeof(TYPE)) {             \
1189         TYPE nn = *(TYPE *)(vn + i);                         \
1190         nn = OP(nn) & MAKE_64BIT_MASK(0, sizeof(TYPE) * 4);  \
1191         *(TYPE *)(vd + i) = nn;                              \
1192     }                                                        \
1193 }
1194 
1195 #define DO_XTNT(NAME, TYPE, TYPEN, H, OP)                               \
1196 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)                    \
1197 {                                                                       \
1198     intptr_t i, opr_sz = simd_oprsz(desc), odd = H(sizeof(TYPEN));      \
1199     for (i = 0; i < opr_sz; i += sizeof(TYPE)) {                        \
1200         TYPE nn = *(TYPE *)(vn + i);                                    \
1201         *(TYPEN *)(vd + i + odd) = OP(nn);                              \
1202     }                                                                   \
1203 }
1204 
1205 #define DO_SQXTN_H(n)  do_sat_bhs(n, INT8_MIN, INT8_MAX)
1206 #define DO_SQXTN_S(n)  do_sat_bhs(n, INT16_MIN, INT16_MAX)
1207 #define DO_SQXTN_D(n)  do_sat_bhs(n, INT32_MIN, INT32_MAX)
1208 
1209 DO_XTNB(sve2_sqxtnb_h, int16_t, DO_SQXTN_H)
1210 DO_XTNB(sve2_sqxtnb_s, int32_t, DO_SQXTN_S)
1211 DO_XTNB(sve2_sqxtnb_d, int64_t, DO_SQXTN_D)
1212 
1213 DO_XTNT(sve2_sqxtnt_h, int16_t, int8_t, H1, DO_SQXTN_H)
1214 DO_XTNT(sve2_sqxtnt_s, int32_t, int16_t, H1_2, DO_SQXTN_S)
1215 DO_XTNT(sve2_sqxtnt_d, int64_t, int32_t, H1_4, DO_SQXTN_D)
1216 
1217 #define DO_UQXTN_H(n)  do_sat_bhs(n, 0, UINT8_MAX)
1218 #define DO_UQXTN_S(n)  do_sat_bhs(n, 0, UINT16_MAX)
1219 #define DO_UQXTN_D(n)  do_sat_bhs(n, 0, UINT32_MAX)
1220 
1221 DO_XTNB(sve2_uqxtnb_h, uint16_t, DO_UQXTN_H)
1222 DO_XTNB(sve2_uqxtnb_s, uint32_t, DO_UQXTN_S)
1223 DO_XTNB(sve2_uqxtnb_d, uint64_t, DO_UQXTN_D)
1224 
1225 DO_XTNT(sve2_uqxtnt_h, uint16_t, uint8_t, H1, DO_UQXTN_H)
1226 DO_XTNT(sve2_uqxtnt_s, uint32_t, uint16_t, H1_2, DO_UQXTN_S)
1227 DO_XTNT(sve2_uqxtnt_d, uint64_t, uint32_t, H1_4, DO_UQXTN_D)
1228 
1229 DO_XTNB(sve2_sqxtunb_h, int16_t, DO_UQXTN_H)
1230 DO_XTNB(sve2_sqxtunb_s, int32_t, DO_UQXTN_S)
1231 DO_XTNB(sve2_sqxtunb_d, int64_t, DO_UQXTN_D)
1232 
1233 DO_XTNT(sve2_sqxtunt_h, int16_t, int8_t, H1, DO_UQXTN_H)
1234 DO_XTNT(sve2_sqxtunt_s, int32_t, int16_t, H1_2, DO_UQXTN_S)
1235 DO_XTNT(sve2_sqxtunt_d, int64_t, int32_t, H1_4, DO_UQXTN_D)
1236 
1237 #undef DO_XTNB
1238 #undef DO_XTNT
1239 
1240 void HELPER(sve2_adcl_s)(void *vd, void *vn, void *vm, void *va, uint32_t desc)
1241 {
1242     intptr_t i, opr_sz = simd_oprsz(desc);
1243     int sel = H4(extract32(desc, SIMD_DATA_SHIFT, 1));
1244     uint32_t inv = -extract32(desc, SIMD_DATA_SHIFT + 1, 1);
1245     uint32_t *a = va, *n = vn;
1246     uint64_t *d = vd, *m = vm;
1247 
1248     for (i = 0; i < opr_sz / 8; ++i) {
1249         uint32_t e1 = a[2 * i + H4(0)];
1250         uint32_t e2 = n[2 * i + sel] ^ inv;
1251         uint64_t c = extract64(m[i], 32, 1);
1252         /* Compute and store the entire 33-bit result at once. */
1253         d[i] = c + e1 + e2;
1254     }
1255 }
1256 
1257 void HELPER(sve2_adcl_d)(void *vd, void *vn, void *vm, void *va, uint32_t desc)
1258 {
1259     intptr_t i, opr_sz = simd_oprsz(desc);
1260     int sel = extract32(desc, SIMD_DATA_SHIFT, 1);
1261     uint64_t inv = -(uint64_t)extract32(desc, SIMD_DATA_SHIFT + 1, 1);
1262     uint64_t *d = vd, *a = va, *n = vn, *m = vm;
1263 
1264     for (i = 0; i < opr_sz / 8; i += 2) {
1265         Int128 e1 = int128_make64(a[i]);
1266         Int128 e2 = int128_make64(n[i + sel] ^ inv);
1267         Int128 c = int128_make64(m[i + 1] & 1);
1268         Int128 r = int128_add(int128_add(e1, e2), c);
1269         d[i + 0] = int128_getlo(r);
1270         d[i + 1] = int128_gethi(r);
1271     }
1272 }
1273 
1274 #define DO_SQDMLAL(NAME, TYPEW, TYPEN, HW, HN, DMUL_OP, SUM_OP) \
1275 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
1276 {                                                                       \
1277     intptr_t i, opr_sz = simd_oprsz(desc);                              \
1278     int sel1 = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPEN);     \
1279     int sel2 = extract32(desc, SIMD_DATA_SHIFT + 1, 1) * sizeof(TYPEN); \
1280     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {                       \
1281         TYPEW nn = *(TYPEN *)(vn + HN(i + sel1));                       \
1282         TYPEW mm = *(TYPEN *)(vm + HN(i + sel2));                       \
1283         TYPEW aa = *(TYPEW *)(va + HW(i));                              \
1284         *(TYPEW *)(vd + HW(i)) = SUM_OP(aa, DMUL_OP(nn, mm));           \
1285     }                                                                   \
1286 }
1287 
1288 DO_SQDMLAL(sve2_sqdmlal_zzzw_h, int16_t, int8_t, H1_2, H1,
1289            do_sqdmull_h, DO_SQADD_H)
1290 DO_SQDMLAL(sve2_sqdmlal_zzzw_s, int32_t, int16_t, H1_4, H1_2,
1291            do_sqdmull_s, DO_SQADD_S)
1292 DO_SQDMLAL(sve2_sqdmlal_zzzw_d, int64_t, int32_t, H1_8, H1_4,
1293            do_sqdmull_d, do_sqadd_d)
1294 
1295 DO_SQDMLAL(sve2_sqdmlsl_zzzw_h, int16_t, int8_t, H1_2, H1,
1296            do_sqdmull_h, DO_SQSUB_H)
1297 DO_SQDMLAL(sve2_sqdmlsl_zzzw_s, int32_t, int16_t, H1_4, H1_2,
1298            do_sqdmull_s, DO_SQSUB_S)
1299 DO_SQDMLAL(sve2_sqdmlsl_zzzw_d, int64_t, int32_t, H1_8, H1_4,
1300            do_sqdmull_d, do_sqsub_d)
1301 
1302 #undef DO_SQDMLAL
1303 
1304 #define DO_CMLA_FUNC(NAME, TYPE, H, OP) \
1305 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
1306 {                                                               \
1307     intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(TYPE);       \
1308     int rot = simd_data(desc);                                  \
1309     int sel_a = rot & 1, sel_b = sel_a ^ 1;                     \
1310     bool sub_r = rot == 1 || rot == 2;                          \
1311     bool sub_i = rot >= 2;                                      \
1312     TYPE *d = vd, *n = vn, *m = vm, *a = va;                    \
1313     for (i = 0; i < opr_sz; i += 2) {                           \
1314         TYPE elt1_a = n[H(i + sel_a)];                          \
1315         TYPE elt2_a = m[H(i + sel_a)];                          \
1316         TYPE elt2_b = m[H(i + sel_b)];                          \
1317         d[H(i)] = OP(elt1_a, elt2_a, a[H(i)], sub_r);           \
1318         d[H(i + 1)] = OP(elt1_a, elt2_b, a[H(i + 1)], sub_i);   \
1319     }                                                           \
1320 }
1321 
1322 #define DO_CMLA(N, M, A, S) (A + (N * M) * (S ? -1 : 1))
1323 
1324 DO_CMLA_FUNC(sve2_cmla_zzzz_b, uint8_t, H1, DO_CMLA)
1325 DO_CMLA_FUNC(sve2_cmla_zzzz_h, uint16_t, H2, DO_CMLA)
1326 DO_CMLA_FUNC(sve2_cmla_zzzz_s, uint32_t, H4, DO_CMLA)
1327 DO_CMLA_FUNC(sve2_cmla_zzzz_d, uint64_t, H8, DO_CMLA)
1328 
1329 #define DO_SQRDMLAH_B(N, M, A, S) \
1330     do_sqrdmlah_b(N, M, A, S, true)
1331 #define DO_SQRDMLAH_H(N, M, A, S) \
1332     ({ uint32_t discard; do_sqrdmlah_h(N, M, A, S, true, &discard); })
1333 #define DO_SQRDMLAH_S(N, M, A, S) \
1334     ({ uint32_t discard; do_sqrdmlah_s(N, M, A, S, true, &discard); })
1335 #define DO_SQRDMLAH_D(N, M, A, S) \
1336     do_sqrdmlah_d(N, M, A, S, true)
1337 
1338 DO_CMLA_FUNC(sve2_sqrdcmlah_zzzz_b, int8_t, H1, DO_SQRDMLAH_B)
1339 DO_CMLA_FUNC(sve2_sqrdcmlah_zzzz_h, int16_t, H2, DO_SQRDMLAH_H)
1340 DO_CMLA_FUNC(sve2_sqrdcmlah_zzzz_s, int32_t, H4, DO_SQRDMLAH_S)
1341 DO_CMLA_FUNC(sve2_sqrdcmlah_zzzz_d, int64_t, H8, DO_SQRDMLAH_D)
1342 
1343 #define DO_CMLA_IDX_FUNC(NAME, TYPE, H, OP) \
1344 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc)    \
1345 {                                                                           \
1346     intptr_t i, j, oprsz = simd_oprsz(desc);                                \
1347     int rot = extract32(desc, SIMD_DATA_SHIFT, 2);                          \
1348     int idx = extract32(desc, SIMD_DATA_SHIFT + 2, 2) * 2;                  \
1349     int sel_a = rot & 1, sel_b = sel_a ^ 1;                                 \
1350     bool sub_r = rot == 1 || rot == 2;                                      \
1351     bool sub_i = rot >= 2;                                                  \
1352     TYPE *d = vd, *n = vn, *m = vm, *a = va;                                \
1353     for (i = 0; i < oprsz / sizeof(TYPE); i += 16 / sizeof(TYPE)) {         \
1354         TYPE elt2_a = m[H(i + idx + sel_a)];                                \
1355         TYPE elt2_b = m[H(i + idx + sel_b)];                                \
1356         for (j = 0; j < 16 / sizeof(TYPE); j += 2) {                        \
1357             TYPE elt1_a = n[H(i + j + sel_a)];                              \
1358             d[H2(i + j)] = OP(elt1_a, elt2_a, a[H(i + j)], sub_r);          \
1359             d[H2(i + j + 1)] = OP(elt1_a, elt2_b, a[H(i + j + 1)], sub_i);  \
1360         }                                                                   \
1361     }                                                                       \
1362 }
1363 
1364 DO_CMLA_IDX_FUNC(sve2_cmla_idx_h, int16_t, H2, DO_CMLA)
1365 DO_CMLA_IDX_FUNC(sve2_cmla_idx_s, int32_t, H4, DO_CMLA)
1366 
1367 DO_CMLA_IDX_FUNC(sve2_sqrdcmlah_idx_h, int16_t, H2, DO_SQRDMLAH_H)
1368 DO_CMLA_IDX_FUNC(sve2_sqrdcmlah_idx_s, int32_t, H4, DO_SQRDMLAH_S)
1369 
1370 #undef DO_CMLA
1371 #undef DO_CMLA_FUNC
1372 #undef DO_CMLA_IDX_FUNC
1373 #undef DO_SQRDMLAH_B
1374 #undef DO_SQRDMLAH_H
1375 #undef DO_SQRDMLAH_S
1376 #undef DO_SQRDMLAH_D
1377 
1378 /* Note N and M are 4 elements bundled into one unit. */
1379 static int32_t do_cdot_s(uint32_t n, uint32_t m, int32_t a,
1380                          int sel_a, int sel_b, int sub_i)
1381 {
1382     for (int i = 0; i <= 1; i++) {
1383         int32_t elt1_r = (int8_t)(n >> (16 * i));
1384         int32_t elt1_i = (int8_t)(n >> (16 * i + 8));
1385         int32_t elt2_a = (int8_t)(m >> (16 * i + 8 * sel_a));
1386         int32_t elt2_b = (int8_t)(m >> (16 * i + 8 * sel_b));
1387 
1388         a += elt1_r * elt2_a + elt1_i * elt2_b * sub_i;
1389     }
1390     return a;
1391 }
1392 
1393 static int64_t do_cdot_d(uint64_t n, uint64_t m, int64_t a,
1394                          int sel_a, int sel_b, int sub_i)
1395 {
1396     for (int i = 0; i <= 1; i++) {
1397         int64_t elt1_r = (int16_t)(n >> (32 * i + 0));
1398         int64_t elt1_i = (int16_t)(n >> (32 * i + 16));
1399         int64_t elt2_a = (int16_t)(m >> (32 * i + 16 * sel_a));
1400         int64_t elt2_b = (int16_t)(m >> (32 * i + 16 * sel_b));
1401 
1402         a += elt1_r * elt2_a + elt1_i * elt2_b * sub_i;
1403     }
1404     return a;
1405 }
1406 
1407 void HELPER(sve2_cdot_zzzz_s)(void *vd, void *vn, void *vm,
1408                               void *va, uint32_t desc)
1409 {
1410     int opr_sz = simd_oprsz(desc);
1411     int rot = simd_data(desc);
1412     int sel_a = rot & 1;
1413     int sel_b = sel_a ^ 1;
1414     int sub_i = (rot == 0 || rot == 3 ? -1 : 1);
1415     uint32_t *d = vd, *n = vn, *m = vm, *a = va;
1416 
1417     for (int e = 0; e < opr_sz / 4; e++) {
1418         d[e] = do_cdot_s(n[e], m[e], a[e], sel_a, sel_b, sub_i);
1419     }
1420 }
1421 
1422 void HELPER(sve2_cdot_zzzz_d)(void *vd, void *vn, void *vm,
1423                               void *va, uint32_t desc)
1424 {
1425     int opr_sz = simd_oprsz(desc);
1426     int rot = simd_data(desc);
1427     int sel_a = rot & 1;
1428     int sel_b = sel_a ^ 1;
1429     int sub_i = (rot == 0 || rot == 3 ? -1 : 1);
1430     uint64_t *d = vd, *n = vn, *m = vm, *a = va;
1431 
1432     for (int e = 0; e < opr_sz / 8; e++) {
1433         d[e] = do_cdot_d(n[e], m[e], a[e], sel_a, sel_b, sub_i);
1434     }
1435 }
1436 
1437 void HELPER(sve2_cdot_idx_s)(void *vd, void *vn, void *vm,
1438                              void *va, uint32_t desc)
1439 {
1440     int opr_sz = simd_oprsz(desc);
1441     int rot = extract32(desc, SIMD_DATA_SHIFT, 2);
1442     int idx = H4(extract32(desc, SIMD_DATA_SHIFT + 2, 2));
1443     int sel_a = rot & 1;
1444     int sel_b = sel_a ^ 1;
1445     int sub_i = (rot == 0 || rot == 3 ? -1 : 1);
1446     uint32_t *d = vd, *n = vn, *m = vm, *a = va;
1447 
1448     for (int seg = 0; seg < opr_sz / 4; seg += 4) {
1449         uint32_t seg_m = m[seg + idx];
1450         for (int e = 0; e < 4; e++) {
1451             d[seg + e] = do_cdot_s(n[seg + e], seg_m, a[seg + e],
1452                                    sel_a, sel_b, sub_i);
1453         }
1454     }
1455 }
1456 
1457 void HELPER(sve2_cdot_idx_d)(void *vd, void *vn, void *vm,
1458                              void *va, uint32_t desc)
1459 {
1460     int seg, opr_sz = simd_oprsz(desc);
1461     int rot = extract32(desc, SIMD_DATA_SHIFT, 2);
1462     int idx = extract32(desc, SIMD_DATA_SHIFT + 2, 2);
1463     int sel_a = rot & 1;
1464     int sel_b = sel_a ^ 1;
1465     int sub_i = (rot == 0 || rot == 3 ? -1 : 1);
1466     uint64_t *d = vd, *n = vn, *m = vm, *a = va;
1467 
1468     for (seg = 0; seg < opr_sz / 8; seg += 2) {
1469         uint64_t seg_m = m[seg + idx];
1470         for (int e = 0; e < 2; e++) {
1471             d[seg + e] = do_cdot_d(n[seg + e], seg_m, a[seg + e],
1472                                    sel_a, sel_b, sub_i);
1473         }
1474     }
1475 }
1476 
1477 #define DO_ZZXZ(NAME, TYPE, H, OP) \
1478 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc) \
1479 {                                                                       \
1480     intptr_t oprsz = simd_oprsz(desc), segment = 16 / sizeof(TYPE);     \
1481     intptr_t i, j, idx = simd_data(desc);                               \
1482     TYPE *d = vd, *a = va, *n = vn, *m = (TYPE *)vm + H(idx);           \
1483     for (i = 0; i < oprsz / sizeof(TYPE); i += segment) {               \
1484         TYPE mm = m[i];                                                 \
1485         for (j = 0; j < segment; j++) {                                 \
1486             d[i + j] = OP(n[i + j], mm, a[i + j]);                      \
1487         }                                                               \
1488     }                                                                   \
1489 }
1490 
1491 #define DO_SQRDMLAH_H(N, M, A) \
1492     ({ uint32_t discard; do_sqrdmlah_h(N, M, A, false, true, &discard); })
1493 #define DO_SQRDMLAH_S(N, M, A) \
1494     ({ uint32_t discard; do_sqrdmlah_s(N, M, A, false, true, &discard); })
1495 #define DO_SQRDMLAH_D(N, M, A) do_sqrdmlah_d(N, M, A, false, true)
1496 
1497 DO_ZZXZ(sve2_sqrdmlah_idx_h, int16_t, H2, DO_SQRDMLAH_H)
1498 DO_ZZXZ(sve2_sqrdmlah_idx_s, int32_t, H4, DO_SQRDMLAH_S)
1499 DO_ZZXZ(sve2_sqrdmlah_idx_d, int64_t, H8, DO_SQRDMLAH_D)
1500 
1501 #define DO_SQRDMLSH_H(N, M, A) \
1502     ({ uint32_t discard; do_sqrdmlah_h(N, M, A, true, true, &discard); })
1503 #define DO_SQRDMLSH_S(N, M, A) \
1504     ({ uint32_t discard; do_sqrdmlah_s(N, M, A, true, true, &discard); })
1505 #define DO_SQRDMLSH_D(N, M, A) do_sqrdmlah_d(N, M, A, true, true)
1506 
1507 DO_ZZXZ(sve2_sqrdmlsh_idx_h, int16_t, H2, DO_SQRDMLSH_H)
1508 DO_ZZXZ(sve2_sqrdmlsh_idx_s, int32_t, H4, DO_SQRDMLSH_S)
1509 DO_ZZXZ(sve2_sqrdmlsh_idx_d, int64_t, H8, DO_SQRDMLSH_D)
1510 
1511 #undef DO_ZZXZ
1512 
1513 #define DO_ZZXW(NAME, TYPEW, TYPEN, HW, HN, OP) \
1514 void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, uint32_t desc)  \
1515 {                                                                         \
1516     intptr_t i, j, oprsz = simd_oprsz(desc);                              \
1517     intptr_t sel = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPEN);   \
1518     intptr_t idx = extract32(desc, SIMD_DATA_SHIFT + 1, 3) * sizeof(TYPEN); \
1519     for (i = 0; i < oprsz; i += 16) {                                     \
1520         TYPEW mm = *(TYPEN *)(vm + HN(i + idx));                          \
1521         for (j = 0; j < 16; j += sizeof(TYPEW)) {                         \
1522             TYPEW nn = *(TYPEN *)(vn + HN(i + j + sel));                  \
1523             TYPEW aa = *(TYPEW *)(va + HW(i + j));                        \
1524             *(TYPEW *)(vd + HW(i + j)) = OP(nn, mm, aa);                  \
1525         }                                                                 \
1526     }                                                                     \
1527 }
1528 
1529 #define DO_MLA(N, M, A)  (A + N * M)
1530 
1531 DO_ZZXW(sve2_smlal_idx_s, int32_t, int16_t, H1_4, H1_2, DO_MLA)
1532 DO_ZZXW(sve2_smlal_idx_d, int64_t, int32_t, H1_8, H1_4, DO_MLA)
1533 DO_ZZXW(sve2_umlal_idx_s, uint32_t, uint16_t, H1_4, H1_2, DO_MLA)
1534 DO_ZZXW(sve2_umlal_idx_d, uint64_t, uint32_t, H1_8, H1_4, DO_MLA)
1535 
1536 #define DO_MLS(N, M, A)  (A - N * M)
1537 
1538 DO_ZZXW(sve2_smlsl_idx_s, int32_t, int16_t, H1_4, H1_2, DO_MLS)
1539 DO_ZZXW(sve2_smlsl_idx_d, int64_t, int32_t, H1_8, H1_4, DO_MLS)
1540 DO_ZZXW(sve2_umlsl_idx_s, uint32_t, uint16_t, H1_4, H1_2, DO_MLS)
1541 DO_ZZXW(sve2_umlsl_idx_d, uint64_t, uint32_t, H1_8, H1_4, DO_MLS)
1542 
1543 #define DO_SQDMLAL_S(N, M, A)  DO_SQADD_S(A, do_sqdmull_s(N, M))
1544 #define DO_SQDMLAL_D(N, M, A)  do_sqadd_d(A, do_sqdmull_d(N, M))
1545 
1546 DO_ZZXW(sve2_sqdmlal_idx_s, int32_t, int16_t, H1_4, H1_2, DO_SQDMLAL_S)
1547 DO_ZZXW(sve2_sqdmlal_idx_d, int64_t, int32_t, H1_8, H1_4, DO_SQDMLAL_D)
1548 
1549 #define DO_SQDMLSL_S(N, M, A)  DO_SQSUB_S(A, do_sqdmull_s(N, M))
1550 #define DO_SQDMLSL_D(N, M, A)  do_sqsub_d(A, do_sqdmull_d(N, M))
1551 
1552 DO_ZZXW(sve2_sqdmlsl_idx_s, int32_t, int16_t, H1_4, H1_2, DO_SQDMLSL_S)
1553 DO_ZZXW(sve2_sqdmlsl_idx_d, int64_t, int32_t, H1_8, H1_4, DO_SQDMLSL_D)
1554 
1555 #undef DO_MLA
1556 #undef DO_MLS
1557 #undef DO_ZZXW
1558 
1559 #define DO_ZZX(NAME, TYPEW, TYPEN, HW, HN, OP) \
1560 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)            \
1561 {                                                                         \
1562     intptr_t i, j, oprsz = simd_oprsz(desc);                              \
1563     intptr_t sel = extract32(desc, SIMD_DATA_SHIFT, 1) * sizeof(TYPEN);   \
1564     intptr_t idx = extract32(desc, SIMD_DATA_SHIFT + 1, 3) * sizeof(TYPEN); \
1565     for (i = 0; i < oprsz; i += 16) {                                     \
1566         TYPEW mm = *(TYPEN *)(vm + HN(i + idx));                          \
1567         for (j = 0; j < 16; j += sizeof(TYPEW)) {                         \
1568             TYPEW nn = *(TYPEN *)(vn + HN(i + j + sel));                  \
1569             *(TYPEW *)(vd + HW(i + j)) = OP(nn, mm);                      \
1570         }                                                                 \
1571     }                                                                     \
1572 }
1573 
1574 DO_ZZX(sve2_sqdmull_idx_s, int32_t, int16_t, H1_4, H1_2, do_sqdmull_s)
1575 DO_ZZX(sve2_sqdmull_idx_d, int64_t, int32_t, H1_8, H1_4, do_sqdmull_d)
1576 
1577 DO_ZZX(sve2_smull_idx_s, int32_t, int16_t, H1_4, H1_2, DO_MUL)
1578 DO_ZZX(sve2_smull_idx_d, int64_t, int32_t, H1_8, H1_4, DO_MUL)
1579 
1580 DO_ZZX(sve2_umull_idx_s, uint32_t, uint16_t, H1_4, H1_2, DO_MUL)
1581 DO_ZZX(sve2_umull_idx_d, uint64_t, uint32_t, H1_8, H1_4, DO_MUL)
1582 
1583 #undef DO_ZZX
1584 
1585 #define DO_BITPERM(NAME, TYPE, OP) \
1586 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
1587 {                                                              \
1588     intptr_t i, opr_sz = simd_oprsz(desc);                     \
1589     for (i = 0; i < opr_sz; i += sizeof(TYPE)) {               \
1590         TYPE nn = *(TYPE *)(vn + i);                           \
1591         TYPE mm = *(TYPE *)(vm + i);                           \
1592         *(TYPE *)(vd + i) = OP(nn, mm, sizeof(TYPE) * 8);      \
1593     }                                                          \
1594 }
1595 
1596 static uint64_t bitextract(uint64_t data, uint64_t mask, int n)
1597 {
1598     uint64_t res = 0;
1599     int db, rb = 0;
1600 
1601     for (db = 0; db < n; ++db) {
1602         if ((mask >> db) & 1) {
1603             res |= ((data >> db) & 1) << rb;
1604             ++rb;
1605         }
1606     }
1607     return res;
1608 }
1609 
1610 DO_BITPERM(sve2_bext_b, uint8_t, bitextract)
1611 DO_BITPERM(sve2_bext_h, uint16_t, bitextract)
1612 DO_BITPERM(sve2_bext_s, uint32_t, bitextract)
1613 DO_BITPERM(sve2_bext_d, uint64_t, bitextract)
1614 
1615 static uint64_t bitdeposit(uint64_t data, uint64_t mask, int n)
1616 {
1617     uint64_t res = 0;
1618     int rb, db = 0;
1619 
1620     for (rb = 0; rb < n; ++rb) {
1621         if ((mask >> rb) & 1) {
1622             res |= ((data >> db) & 1) << rb;
1623             ++db;
1624         }
1625     }
1626     return res;
1627 }
1628 
1629 DO_BITPERM(sve2_bdep_b, uint8_t, bitdeposit)
1630 DO_BITPERM(sve2_bdep_h, uint16_t, bitdeposit)
1631 DO_BITPERM(sve2_bdep_s, uint32_t, bitdeposit)
1632 DO_BITPERM(sve2_bdep_d, uint64_t, bitdeposit)
1633 
1634 static uint64_t bitgroup(uint64_t data, uint64_t mask, int n)
1635 {
1636     uint64_t resm = 0, resu = 0;
1637     int db, rbm = 0, rbu = 0;
1638 
1639     for (db = 0; db < n; ++db) {
1640         uint64_t val = (data >> db) & 1;
1641         if ((mask >> db) & 1) {
1642             resm |= val << rbm++;
1643         } else {
1644             resu |= val << rbu++;
1645         }
1646     }
1647 
1648     return resm | (resu << rbm);
1649 }
1650 
1651 DO_BITPERM(sve2_bgrp_b, uint8_t, bitgroup)
1652 DO_BITPERM(sve2_bgrp_h, uint16_t, bitgroup)
1653 DO_BITPERM(sve2_bgrp_s, uint32_t, bitgroup)
1654 DO_BITPERM(sve2_bgrp_d, uint64_t, bitgroup)
1655 
1656 #undef DO_BITPERM
1657 
1658 #define DO_CADD(NAME, TYPE, H, ADD_OP, SUB_OP)                  \
1659 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)  \
1660 {                                                               \
1661     intptr_t i, opr_sz = simd_oprsz(desc);                      \
1662     int sub_r = simd_data(desc);                                \
1663     if (sub_r) {                                                \
1664         for (i = 0; i < opr_sz; i += 2 * sizeof(TYPE)) {        \
1665             TYPE acc_r = *(TYPE *)(vn + H(i));                  \
1666             TYPE acc_i = *(TYPE *)(vn + H(i + sizeof(TYPE)));   \
1667             TYPE el2_r = *(TYPE *)(vm + H(i));                  \
1668             TYPE el2_i = *(TYPE *)(vm + H(i + sizeof(TYPE)));   \
1669             acc_r = ADD_OP(acc_r, el2_i);                       \
1670             acc_i = SUB_OP(acc_i, el2_r);                       \
1671             *(TYPE *)(vd + H(i)) = acc_r;                       \
1672             *(TYPE *)(vd + H(i + sizeof(TYPE))) = acc_i;        \
1673         }                                                       \
1674     } else {                                                    \
1675         for (i = 0; i < opr_sz; i += 2 * sizeof(TYPE)) {        \
1676             TYPE acc_r = *(TYPE *)(vn + H(i));                  \
1677             TYPE acc_i = *(TYPE *)(vn + H(i + sizeof(TYPE)));   \
1678             TYPE el2_r = *(TYPE *)(vm + H(i));                  \
1679             TYPE el2_i = *(TYPE *)(vm + H(i + sizeof(TYPE)));   \
1680             acc_r = SUB_OP(acc_r, el2_i);                       \
1681             acc_i = ADD_OP(acc_i, el2_r);                       \
1682             *(TYPE *)(vd + H(i)) = acc_r;                       \
1683             *(TYPE *)(vd + H(i + sizeof(TYPE))) = acc_i;        \
1684         }                                                       \
1685     }                                                           \
1686 }
1687 
1688 DO_CADD(sve2_cadd_b, int8_t, H1, DO_ADD, DO_SUB)
1689 DO_CADD(sve2_cadd_h, int16_t, H1_2, DO_ADD, DO_SUB)
1690 DO_CADD(sve2_cadd_s, int32_t, H1_4, DO_ADD, DO_SUB)
1691 DO_CADD(sve2_cadd_d, int64_t, H1_8, DO_ADD, DO_SUB)
1692 
1693 DO_CADD(sve2_sqcadd_b, int8_t, H1, DO_SQADD_B, DO_SQSUB_B)
1694 DO_CADD(sve2_sqcadd_h, int16_t, H1_2, DO_SQADD_H, DO_SQSUB_H)
1695 DO_CADD(sve2_sqcadd_s, int32_t, H1_4, DO_SQADD_S, DO_SQSUB_S)
1696 DO_CADD(sve2_sqcadd_d, int64_t, H1_8, do_sqadd_d, do_sqsub_d)
1697 
1698 #undef DO_CADD
1699 
1700 #define DO_ZZI_SHLL(NAME, TYPEW, TYPEN, HW, HN) \
1701 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)           \
1702 {                                                              \
1703     intptr_t i, opr_sz = simd_oprsz(desc);                     \
1704     intptr_t sel = (simd_data(desc) & 1) * sizeof(TYPEN);      \
1705     int shift = simd_data(desc) >> 1;                          \
1706     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {              \
1707         TYPEW nn = *(TYPEN *)(vn + HN(i + sel));               \
1708         *(TYPEW *)(vd + HW(i)) = nn << shift;                  \
1709     }                                                          \
1710 }
1711 
1712 DO_ZZI_SHLL(sve2_sshll_h, int16_t, int8_t, H1_2, H1)
1713 DO_ZZI_SHLL(sve2_sshll_s, int32_t, int16_t, H1_4, H1_2)
1714 DO_ZZI_SHLL(sve2_sshll_d, int64_t, int32_t, H1_8, H1_4)
1715 
1716 DO_ZZI_SHLL(sve2_ushll_h, uint16_t, uint8_t, H1_2, H1)
1717 DO_ZZI_SHLL(sve2_ushll_s, uint32_t, uint16_t, H1_4, H1_2)
1718 DO_ZZI_SHLL(sve2_ushll_d, uint64_t, uint32_t, H1_8, H1_4)
1719 
1720 #undef DO_ZZI_SHLL
1721 
1722 /* Two-operand reduction expander, controlled by a predicate.
1723  * The difference between TYPERED and TYPERET has to do with
1724  * sign-extension.  E.g. for SMAX, TYPERED must be signed,
1725  * but TYPERET must be unsigned so that e.g. a 32-bit value
1726  * is not sign-extended to the ABI uint64_t return type.
1727  */
1728 /* ??? If we were to vectorize this by hand the reduction ordering
1729  * would change.  For integer operands, this is perfectly fine.
1730  */
1731 #define DO_VPZ(NAME, TYPEELT, TYPERED, TYPERET, H, INIT, OP) \
1732 uint64_t HELPER(NAME)(void *vn, void *vg, uint32_t desc)   \
1733 {                                                          \
1734     intptr_t i, opr_sz = simd_oprsz(desc);                 \
1735     TYPERED ret = INIT;                                    \
1736     for (i = 0; i < opr_sz; ) {                            \
1737         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));    \
1738         do {                                               \
1739             if (pg & 1) {                                  \
1740                 TYPEELT nn = *(TYPEELT *)(vn + H(i));      \
1741                 ret = OP(ret, nn);                         \
1742             }                                              \
1743             i += sizeof(TYPEELT), pg >>= sizeof(TYPEELT);  \
1744         } while (i & 15);                                  \
1745     }                                                      \
1746     return (TYPERET)ret;                                   \
1747 }
1748 
1749 #define DO_VPZ_D(NAME, TYPEE, TYPER, INIT, OP)             \
1750 uint64_t HELPER(NAME)(void *vn, void *vg, uint32_t desc)   \
1751 {                                                          \
1752     intptr_t i, opr_sz = simd_oprsz(desc) / 8;             \
1753     TYPEE *n = vn;                                         \
1754     uint8_t *pg = vg;                                      \
1755     TYPER ret = INIT;                                      \
1756     for (i = 0; i < opr_sz; i += 1) {                      \
1757         if (pg[H1(i)] & 1) {                               \
1758             TYPEE nn = n[i];                               \
1759             ret = OP(ret, nn);                             \
1760         }                                                  \
1761     }                                                      \
1762     return ret;                                            \
1763 }
1764 
1765 DO_VPZ(sve_orv_b, uint8_t, uint8_t, uint8_t, H1, 0, DO_ORR)
1766 DO_VPZ(sve_orv_h, uint16_t, uint16_t, uint16_t, H1_2, 0, DO_ORR)
1767 DO_VPZ(sve_orv_s, uint32_t, uint32_t, uint32_t, H1_4, 0, DO_ORR)
1768 DO_VPZ_D(sve_orv_d, uint64_t, uint64_t, 0, DO_ORR)
1769 
1770 DO_VPZ(sve_eorv_b, uint8_t, uint8_t, uint8_t, H1, 0, DO_EOR)
1771 DO_VPZ(sve_eorv_h, uint16_t, uint16_t, uint16_t, H1_2, 0, DO_EOR)
1772 DO_VPZ(sve_eorv_s, uint32_t, uint32_t, uint32_t, H1_4, 0, DO_EOR)
1773 DO_VPZ_D(sve_eorv_d, uint64_t, uint64_t, 0, DO_EOR)
1774 
1775 DO_VPZ(sve_andv_b, uint8_t, uint8_t, uint8_t, H1, -1, DO_AND)
1776 DO_VPZ(sve_andv_h, uint16_t, uint16_t, uint16_t, H1_2, -1, DO_AND)
1777 DO_VPZ(sve_andv_s, uint32_t, uint32_t, uint32_t, H1_4, -1, DO_AND)
1778 DO_VPZ_D(sve_andv_d, uint64_t, uint64_t, -1, DO_AND)
1779 
1780 DO_VPZ(sve_saddv_b, int8_t, uint64_t, uint64_t, H1, 0, DO_ADD)
1781 DO_VPZ(sve_saddv_h, int16_t, uint64_t, uint64_t, H1_2, 0, DO_ADD)
1782 DO_VPZ(sve_saddv_s, int32_t, uint64_t, uint64_t, H1_4, 0, DO_ADD)
1783 
1784 DO_VPZ(sve_uaddv_b, uint8_t, uint64_t, uint64_t, H1, 0, DO_ADD)
1785 DO_VPZ(sve_uaddv_h, uint16_t, uint64_t, uint64_t, H1_2, 0, DO_ADD)
1786 DO_VPZ(sve_uaddv_s, uint32_t, uint64_t, uint64_t, H1_4, 0, DO_ADD)
1787 DO_VPZ_D(sve_uaddv_d, uint64_t, uint64_t, 0, DO_ADD)
1788 
1789 DO_VPZ(sve_smaxv_b, int8_t, int8_t, uint8_t, H1, INT8_MIN, DO_MAX)
1790 DO_VPZ(sve_smaxv_h, int16_t, int16_t, uint16_t, H1_2, INT16_MIN, DO_MAX)
1791 DO_VPZ(sve_smaxv_s, int32_t, int32_t, uint32_t, H1_4, INT32_MIN, DO_MAX)
1792 DO_VPZ_D(sve_smaxv_d, int64_t, int64_t, INT64_MIN, DO_MAX)
1793 
1794 DO_VPZ(sve_umaxv_b, uint8_t, uint8_t, uint8_t, H1, 0, DO_MAX)
1795 DO_VPZ(sve_umaxv_h, uint16_t, uint16_t, uint16_t, H1_2, 0, DO_MAX)
1796 DO_VPZ(sve_umaxv_s, uint32_t, uint32_t, uint32_t, H1_4, 0, DO_MAX)
1797 DO_VPZ_D(sve_umaxv_d, uint64_t, uint64_t, 0, DO_MAX)
1798 
1799 DO_VPZ(sve_sminv_b, int8_t, int8_t, uint8_t, H1, INT8_MAX, DO_MIN)
1800 DO_VPZ(sve_sminv_h, int16_t, int16_t, uint16_t, H1_2, INT16_MAX, DO_MIN)
1801 DO_VPZ(sve_sminv_s, int32_t, int32_t, uint32_t, H1_4, INT32_MAX, DO_MIN)
1802 DO_VPZ_D(sve_sminv_d, int64_t, int64_t, INT64_MAX, DO_MIN)
1803 
1804 DO_VPZ(sve_uminv_b, uint8_t, uint8_t, uint8_t, H1, -1, DO_MIN)
1805 DO_VPZ(sve_uminv_h, uint16_t, uint16_t, uint16_t, H1_2, -1, DO_MIN)
1806 DO_VPZ(sve_uminv_s, uint32_t, uint32_t, uint32_t, H1_4, -1, DO_MIN)
1807 DO_VPZ_D(sve_uminv_d, uint64_t, uint64_t, -1, DO_MIN)
1808 
1809 #undef DO_VPZ
1810 #undef DO_VPZ_D
1811 
1812 /* Two vector operand, one scalar operand, unpredicated.  */
1813 #define DO_ZZI(NAME, TYPE, OP)                                       \
1814 void HELPER(NAME)(void *vd, void *vn, uint64_t s64, uint32_t desc)   \
1815 {                                                                    \
1816     intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(TYPE);            \
1817     TYPE s = s64, *d = vd, *n = vn;                                  \
1818     for (i = 0; i < opr_sz; ++i) {                                   \
1819         d[i] = OP(n[i], s);                                          \
1820     }                                                                \
1821 }
1822 
1823 #define DO_SUBR(X, Y)   (Y - X)
1824 
1825 DO_ZZI(sve_subri_b, uint8_t, DO_SUBR)
1826 DO_ZZI(sve_subri_h, uint16_t, DO_SUBR)
1827 DO_ZZI(sve_subri_s, uint32_t, DO_SUBR)
1828 DO_ZZI(sve_subri_d, uint64_t, DO_SUBR)
1829 
1830 DO_ZZI(sve_smaxi_b, int8_t, DO_MAX)
1831 DO_ZZI(sve_smaxi_h, int16_t, DO_MAX)
1832 DO_ZZI(sve_smaxi_s, int32_t, DO_MAX)
1833 DO_ZZI(sve_smaxi_d, int64_t, DO_MAX)
1834 
1835 DO_ZZI(sve_smini_b, int8_t, DO_MIN)
1836 DO_ZZI(sve_smini_h, int16_t, DO_MIN)
1837 DO_ZZI(sve_smini_s, int32_t, DO_MIN)
1838 DO_ZZI(sve_smini_d, int64_t, DO_MIN)
1839 
1840 DO_ZZI(sve_umaxi_b, uint8_t, DO_MAX)
1841 DO_ZZI(sve_umaxi_h, uint16_t, DO_MAX)
1842 DO_ZZI(sve_umaxi_s, uint32_t, DO_MAX)
1843 DO_ZZI(sve_umaxi_d, uint64_t, DO_MAX)
1844 
1845 DO_ZZI(sve_umini_b, uint8_t, DO_MIN)
1846 DO_ZZI(sve_umini_h, uint16_t, DO_MIN)
1847 DO_ZZI(sve_umini_s, uint32_t, DO_MIN)
1848 DO_ZZI(sve_umini_d, uint64_t, DO_MIN)
1849 
1850 #undef DO_ZZI
1851 
1852 #undef DO_AND
1853 #undef DO_ORR
1854 #undef DO_EOR
1855 #undef DO_BIC
1856 #undef DO_ADD
1857 #undef DO_SUB
1858 #undef DO_MAX
1859 #undef DO_MIN
1860 #undef DO_ABD
1861 #undef DO_MUL
1862 #undef DO_DIV
1863 #undef DO_ASR
1864 #undef DO_LSR
1865 #undef DO_LSL
1866 #undef DO_SUBR
1867 
1868 /* Similar to the ARM LastActiveElement pseudocode function, except the
1869    result is multiplied by the element size.  This includes the not found
1870    indication; e.g. not found for esz=3 is -8.  */
1871 static intptr_t last_active_element(uint64_t *g, intptr_t words, intptr_t esz)
1872 {
1873     uint64_t mask = pred_esz_masks[esz];
1874     intptr_t i = words;
1875 
1876     do {
1877         uint64_t this_g = g[--i] & mask;
1878         if (this_g) {
1879             return i * 64 + (63 - clz64(this_g));
1880         }
1881     } while (i > 0);
1882     return (intptr_t)-1 << esz;
1883 }
1884 
1885 uint32_t HELPER(sve_pfirst)(void *vd, void *vg, uint32_t pred_desc)
1886 {
1887     intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
1888     uint32_t flags = PREDTEST_INIT;
1889     uint64_t *d = vd, *g = vg;
1890     intptr_t i = 0;
1891 
1892     do {
1893         uint64_t this_d = d[i];
1894         uint64_t this_g = g[i];
1895 
1896         if (this_g) {
1897             if (!(flags & 4)) {
1898                 /* Set in D the first bit of G.  */
1899                 this_d |= this_g & -this_g;
1900                 d[i] = this_d;
1901             }
1902             flags = iter_predtest_fwd(this_d, this_g, flags);
1903         }
1904     } while (++i < words);
1905 
1906     return flags;
1907 }
1908 
1909 uint32_t HELPER(sve_pnext)(void *vd, void *vg, uint32_t pred_desc)
1910 {
1911     intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
1912     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
1913     uint32_t flags = PREDTEST_INIT;
1914     uint64_t *d = vd, *g = vg, esz_mask;
1915     intptr_t i, next;
1916 
1917     next = last_active_element(vd, words, esz) + (1 << esz);
1918     esz_mask = pred_esz_masks[esz];
1919 
1920     /* Similar to the pseudocode for pnext, but scaled by ESZ
1921        so that we find the correct bit.  */
1922     if (next < words * 64) {
1923         uint64_t mask = -1;
1924 
1925         if (next & 63) {
1926             mask = ~((1ull << (next & 63)) - 1);
1927             next &= -64;
1928         }
1929         do {
1930             uint64_t this_g = g[next / 64] & esz_mask & mask;
1931             if (this_g != 0) {
1932                 next = (next & -64) + ctz64(this_g);
1933                 break;
1934             }
1935             next += 64;
1936             mask = -1;
1937         } while (next < words * 64);
1938     }
1939 
1940     i = 0;
1941     do {
1942         uint64_t this_d = 0;
1943         if (i == next / 64) {
1944             this_d = 1ull << (next & 63);
1945         }
1946         d[i] = this_d;
1947         flags = iter_predtest_fwd(this_d, g[i] & esz_mask, flags);
1948     } while (++i < words);
1949 
1950     return flags;
1951 }
1952 
1953 /*
1954  * Copy Zn into Zd, and store zero into inactive elements.
1955  * If inv, store zeros into the active elements.
1956  */
1957 void HELPER(sve_movz_b)(void *vd, void *vn, void *vg, uint32_t desc)
1958 {
1959     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
1960     uint64_t inv = -(uint64_t)(simd_data(desc) & 1);
1961     uint64_t *d = vd, *n = vn;
1962     uint8_t *pg = vg;
1963 
1964     for (i = 0; i < opr_sz; i += 1) {
1965         d[i] = n[i] & (expand_pred_b(pg[H1(i)]) ^ inv);
1966     }
1967 }
1968 
1969 void HELPER(sve_movz_h)(void *vd, void *vn, void *vg, uint32_t desc)
1970 {
1971     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
1972     uint64_t inv = -(uint64_t)(simd_data(desc) & 1);
1973     uint64_t *d = vd, *n = vn;
1974     uint8_t *pg = vg;
1975 
1976     for (i = 0; i < opr_sz; i += 1) {
1977         d[i] = n[i] & (expand_pred_h(pg[H1(i)]) ^ inv);
1978     }
1979 }
1980 
1981 void HELPER(sve_movz_s)(void *vd, void *vn, void *vg, uint32_t desc)
1982 {
1983     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
1984     uint64_t inv = -(uint64_t)(simd_data(desc) & 1);
1985     uint64_t *d = vd, *n = vn;
1986     uint8_t *pg = vg;
1987 
1988     for (i = 0; i < opr_sz; i += 1) {
1989         d[i] = n[i] & (expand_pred_s(pg[H1(i)]) ^ inv);
1990     }
1991 }
1992 
1993 void HELPER(sve_movz_d)(void *vd, void *vn, void *vg, uint32_t desc)
1994 {
1995     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
1996     uint64_t *d = vd, *n = vn;
1997     uint8_t *pg = vg;
1998     uint8_t inv = simd_data(desc);
1999 
2000     for (i = 0; i < opr_sz; i += 1) {
2001         d[i] = n[i] & -(uint64_t)((pg[H1(i)] ^ inv) & 1);
2002     }
2003 }
2004 
2005 /* Three-operand expander, immediate operand, controlled by a predicate.
2006  */
2007 #define DO_ZPZI(NAME, TYPE, H, OP)                              \
2008 void HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc)  \
2009 {                                                               \
2010     intptr_t i, opr_sz = simd_oprsz(desc);                      \
2011     TYPE imm = simd_data(desc);                                 \
2012     for (i = 0; i < opr_sz; ) {                                 \
2013         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));         \
2014         do {                                                    \
2015             if (pg & 1) {                                       \
2016                 TYPE nn = *(TYPE *)(vn + H(i));                 \
2017                 *(TYPE *)(vd + H(i)) = OP(nn, imm);             \
2018             }                                                   \
2019             i += sizeof(TYPE), pg >>= sizeof(TYPE);             \
2020         } while (i & 15);                                       \
2021     }                                                           \
2022 }
2023 
2024 /* Similarly, specialized for 64-bit operands.  */
2025 #define DO_ZPZI_D(NAME, TYPE, OP)                               \
2026 void HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc)  \
2027 {                                                               \
2028     intptr_t i, opr_sz = simd_oprsz(desc) / 8;                  \
2029     TYPE *d = vd, *n = vn;                                      \
2030     TYPE imm = simd_data(desc);                                 \
2031     uint8_t *pg = vg;                                           \
2032     for (i = 0; i < opr_sz; i += 1) {                           \
2033         if (pg[H1(i)] & 1) {                                    \
2034             TYPE nn = n[i];                                     \
2035             d[i] = OP(nn, imm);                                 \
2036         }                                                       \
2037     }                                                           \
2038 }
2039 
2040 #define DO_SHR(N, M)  (N >> M)
2041 #define DO_SHL(N, M)  (N << M)
2042 
2043 /* Arithmetic shift right for division.  This rounds negative numbers
2044    toward zero as per signed division.  Therefore before shifting,
2045    when N is negative, add 2**M-1.  */
2046 #define DO_ASRD(N, M) ((N + (N < 0 ? ((__typeof(N))1 << M) - 1 : 0)) >> M)
2047 
2048 static inline uint64_t do_urshr(uint64_t x, unsigned sh)
2049 {
2050     if (likely(sh < 64)) {
2051         return (x >> sh) + ((x >> (sh - 1)) & 1);
2052     } else if (sh == 64) {
2053         return x >> 63;
2054     } else {
2055         return 0;
2056     }
2057 }
2058 
2059 static inline int64_t do_srshr(int64_t x, unsigned sh)
2060 {
2061     if (likely(sh < 64)) {
2062         return (x >> sh) + ((x >> (sh - 1)) & 1);
2063     } else {
2064         /* Rounding the sign bit always produces 0. */
2065         return 0;
2066     }
2067 }
2068 
2069 DO_ZPZI(sve_asr_zpzi_b, int8_t, H1, DO_SHR)
2070 DO_ZPZI(sve_asr_zpzi_h, int16_t, H1_2, DO_SHR)
2071 DO_ZPZI(sve_asr_zpzi_s, int32_t, H1_4, DO_SHR)
2072 DO_ZPZI_D(sve_asr_zpzi_d, int64_t, DO_SHR)
2073 
2074 DO_ZPZI(sve_lsr_zpzi_b, uint8_t, H1, DO_SHR)
2075 DO_ZPZI(sve_lsr_zpzi_h, uint16_t, H1_2, DO_SHR)
2076 DO_ZPZI(sve_lsr_zpzi_s, uint32_t, H1_4, DO_SHR)
2077 DO_ZPZI_D(sve_lsr_zpzi_d, uint64_t, DO_SHR)
2078 
2079 DO_ZPZI(sve_lsl_zpzi_b, uint8_t, H1, DO_SHL)
2080 DO_ZPZI(sve_lsl_zpzi_h, uint16_t, H1_2, DO_SHL)
2081 DO_ZPZI(sve_lsl_zpzi_s, uint32_t, H1_4, DO_SHL)
2082 DO_ZPZI_D(sve_lsl_zpzi_d, uint64_t, DO_SHL)
2083 
2084 DO_ZPZI(sve_asrd_b, int8_t, H1, DO_ASRD)
2085 DO_ZPZI(sve_asrd_h, int16_t, H1_2, DO_ASRD)
2086 DO_ZPZI(sve_asrd_s, int32_t, H1_4, DO_ASRD)
2087 DO_ZPZI_D(sve_asrd_d, int64_t, DO_ASRD)
2088 
2089 /* SVE2 bitwise shift by immediate */
2090 DO_ZPZI(sve2_sqshl_zpzi_b, int8_t, H1, do_sqshl_b)
2091 DO_ZPZI(sve2_sqshl_zpzi_h, int16_t, H1_2, do_sqshl_h)
2092 DO_ZPZI(sve2_sqshl_zpzi_s, int32_t, H1_4, do_sqshl_s)
2093 DO_ZPZI_D(sve2_sqshl_zpzi_d, int64_t, do_sqshl_d)
2094 
2095 DO_ZPZI(sve2_uqshl_zpzi_b, uint8_t, H1, do_uqshl_b)
2096 DO_ZPZI(sve2_uqshl_zpzi_h, uint16_t, H1_2, do_uqshl_h)
2097 DO_ZPZI(sve2_uqshl_zpzi_s, uint32_t, H1_4, do_uqshl_s)
2098 DO_ZPZI_D(sve2_uqshl_zpzi_d, uint64_t, do_uqshl_d)
2099 
2100 DO_ZPZI(sve2_srshr_b, int8_t, H1, do_srshr)
2101 DO_ZPZI(sve2_srshr_h, int16_t, H1_2, do_srshr)
2102 DO_ZPZI(sve2_srshr_s, int32_t, H1_4, do_srshr)
2103 DO_ZPZI_D(sve2_srshr_d, int64_t, do_srshr)
2104 
2105 DO_ZPZI(sve2_urshr_b, uint8_t, H1, do_urshr)
2106 DO_ZPZI(sve2_urshr_h, uint16_t, H1_2, do_urshr)
2107 DO_ZPZI(sve2_urshr_s, uint32_t, H1_4, do_urshr)
2108 DO_ZPZI_D(sve2_urshr_d, uint64_t, do_urshr)
2109 
2110 #define do_suqrshl_b(n, m) \
2111    ({ uint32_t discard; do_suqrshl_bhs(n, (int8_t)m, 8, false, &discard); })
2112 #define do_suqrshl_h(n, m) \
2113    ({ uint32_t discard; do_suqrshl_bhs(n, (int16_t)m, 16, false, &discard); })
2114 #define do_suqrshl_s(n, m) \
2115    ({ uint32_t discard; do_suqrshl_bhs(n, m, 32, false, &discard); })
2116 #define do_suqrshl_d(n, m) \
2117    ({ uint32_t discard; do_suqrshl_d(n, m, false, &discard); })
2118 
2119 DO_ZPZI(sve2_sqshlu_b, int8_t, H1, do_suqrshl_b)
2120 DO_ZPZI(sve2_sqshlu_h, int16_t, H1_2, do_suqrshl_h)
2121 DO_ZPZI(sve2_sqshlu_s, int32_t, H1_4, do_suqrshl_s)
2122 DO_ZPZI_D(sve2_sqshlu_d, int64_t, do_suqrshl_d)
2123 
2124 #undef DO_ASRD
2125 #undef DO_ZPZI
2126 #undef DO_ZPZI_D
2127 
2128 #define DO_SHRNB(NAME, TYPEW, TYPEN, OP) \
2129 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)         \
2130 {                                                            \
2131     intptr_t i, opr_sz = simd_oprsz(desc);                   \
2132     int shift = simd_data(desc);                             \
2133     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {            \
2134         TYPEW nn = *(TYPEW *)(vn + i);                       \
2135         *(TYPEW *)(vd + i) = (TYPEN)OP(nn, shift);           \
2136     }                                                        \
2137 }
2138 
2139 #define DO_SHRNT(NAME, TYPEW, TYPEN, HW, HN, OP)                  \
2140 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)              \
2141 {                                                                 \
2142     intptr_t i, opr_sz = simd_oprsz(desc);                        \
2143     int shift = simd_data(desc);                                  \
2144     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {                 \
2145         TYPEW nn = *(TYPEW *)(vn + HW(i));                        \
2146         *(TYPEN *)(vd + HN(i + sizeof(TYPEN))) = OP(nn, shift);   \
2147     }                                                             \
2148 }
2149 
2150 DO_SHRNB(sve2_shrnb_h, uint16_t, uint8_t, DO_SHR)
2151 DO_SHRNB(sve2_shrnb_s, uint32_t, uint16_t, DO_SHR)
2152 DO_SHRNB(sve2_shrnb_d, uint64_t, uint32_t, DO_SHR)
2153 
2154 DO_SHRNT(sve2_shrnt_h, uint16_t, uint8_t, H1_2, H1, DO_SHR)
2155 DO_SHRNT(sve2_shrnt_s, uint32_t, uint16_t, H1_4, H1_2, DO_SHR)
2156 DO_SHRNT(sve2_shrnt_d, uint64_t, uint32_t, H1_8, H1_4, DO_SHR)
2157 
2158 DO_SHRNB(sve2_rshrnb_h, uint16_t, uint8_t, do_urshr)
2159 DO_SHRNB(sve2_rshrnb_s, uint32_t, uint16_t, do_urshr)
2160 DO_SHRNB(sve2_rshrnb_d, uint64_t, uint32_t, do_urshr)
2161 
2162 DO_SHRNT(sve2_rshrnt_h, uint16_t, uint8_t, H1_2, H1, do_urshr)
2163 DO_SHRNT(sve2_rshrnt_s, uint32_t, uint16_t, H1_4, H1_2, do_urshr)
2164 DO_SHRNT(sve2_rshrnt_d, uint64_t, uint32_t, H1_8, H1_4, do_urshr)
2165 
2166 #define DO_SQSHRUN_H(x, sh) do_sat_bhs((int64_t)(x) >> sh, 0, UINT8_MAX)
2167 #define DO_SQSHRUN_S(x, sh) do_sat_bhs((int64_t)(x) >> sh, 0, UINT16_MAX)
2168 #define DO_SQSHRUN_D(x, sh) \
2169     do_sat_bhs((int64_t)(x) >> (sh < 64 ? sh : 63), 0, UINT32_MAX)
2170 
2171 DO_SHRNB(sve2_sqshrunb_h, int16_t, uint8_t, DO_SQSHRUN_H)
2172 DO_SHRNB(sve2_sqshrunb_s, int32_t, uint16_t, DO_SQSHRUN_S)
2173 DO_SHRNB(sve2_sqshrunb_d, int64_t, uint32_t, DO_SQSHRUN_D)
2174 
2175 DO_SHRNT(sve2_sqshrunt_h, int16_t, uint8_t, H1_2, H1, DO_SQSHRUN_H)
2176 DO_SHRNT(sve2_sqshrunt_s, int32_t, uint16_t, H1_4, H1_2, DO_SQSHRUN_S)
2177 DO_SHRNT(sve2_sqshrunt_d, int64_t, uint32_t, H1_8, H1_4, DO_SQSHRUN_D)
2178 
2179 #define DO_SQRSHRUN_H(x, sh) do_sat_bhs(do_srshr(x, sh), 0, UINT8_MAX)
2180 #define DO_SQRSHRUN_S(x, sh) do_sat_bhs(do_srshr(x, sh), 0, UINT16_MAX)
2181 #define DO_SQRSHRUN_D(x, sh) do_sat_bhs(do_srshr(x, sh), 0, UINT32_MAX)
2182 
2183 DO_SHRNB(sve2_sqrshrunb_h, int16_t, uint8_t, DO_SQRSHRUN_H)
2184 DO_SHRNB(sve2_sqrshrunb_s, int32_t, uint16_t, DO_SQRSHRUN_S)
2185 DO_SHRNB(sve2_sqrshrunb_d, int64_t, uint32_t, DO_SQRSHRUN_D)
2186 
2187 DO_SHRNT(sve2_sqrshrunt_h, int16_t, uint8_t, H1_2, H1, DO_SQRSHRUN_H)
2188 DO_SHRNT(sve2_sqrshrunt_s, int32_t, uint16_t, H1_4, H1_2, DO_SQRSHRUN_S)
2189 DO_SHRNT(sve2_sqrshrunt_d, int64_t, uint32_t, H1_8, H1_4, DO_SQRSHRUN_D)
2190 
2191 #define DO_SQSHRN_H(x, sh) do_sat_bhs(x >> sh, INT8_MIN, INT8_MAX)
2192 #define DO_SQSHRN_S(x, sh) do_sat_bhs(x >> sh, INT16_MIN, INT16_MAX)
2193 #define DO_SQSHRN_D(x, sh) do_sat_bhs(x >> sh, INT32_MIN, INT32_MAX)
2194 
2195 DO_SHRNB(sve2_sqshrnb_h, int16_t, uint8_t, DO_SQSHRN_H)
2196 DO_SHRNB(sve2_sqshrnb_s, int32_t, uint16_t, DO_SQSHRN_S)
2197 DO_SHRNB(sve2_sqshrnb_d, int64_t, uint32_t, DO_SQSHRN_D)
2198 
2199 DO_SHRNT(sve2_sqshrnt_h, int16_t, uint8_t, H1_2, H1, DO_SQSHRN_H)
2200 DO_SHRNT(sve2_sqshrnt_s, int32_t, uint16_t, H1_4, H1_2, DO_SQSHRN_S)
2201 DO_SHRNT(sve2_sqshrnt_d, int64_t, uint32_t, H1_8, H1_4, DO_SQSHRN_D)
2202 
2203 #define DO_SQRSHRN_H(x, sh) do_sat_bhs(do_srshr(x, sh), INT8_MIN, INT8_MAX)
2204 #define DO_SQRSHRN_S(x, sh) do_sat_bhs(do_srshr(x, sh), INT16_MIN, INT16_MAX)
2205 #define DO_SQRSHRN_D(x, sh) do_sat_bhs(do_srshr(x, sh), INT32_MIN, INT32_MAX)
2206 
2207 DO_SHRNB(sve2_sqrshrnb_h, int16_t, uint8_t, DO_SQRSHRN_H)
2208 DO_SHRNB(sve2_sqrshrnb_s, int32_t, uint16_t, DO_SQRSHRN_S)
2209 DO_SHRNB(sve2_sqrshrnb_d, int64_t, uint32_t, DO_SQRSHRN_D)
2210 
2211 DO_SHRNT(sve2_sqrshrnt_h, int16_t, uint8_t, H1_2, H1, DO_SQRSHRN_H)
2212 DO_SHRNT(sve2_sqrshrnt_s, int32_t, uint16_t, H1_4, H1_2, DO_SQRSHRN_S)
2213 DO_SHRNT(sve2_sqrshrnt_d, int64_t, uint32_t, H1_8, H1_4, DO_SQRSHRN_D)
2214 
2215 #define DO_UQSHRN_H(x, sh) MIN(x >> sh, UINT8_MAX)
2216 #define DO_UQSHRN_S(x, sh) MIN(x >> sh, UINT16_MAX)
2217 #define DO_UQSHRN_D(x, sh) MIN(x >> sh, UINT32_MAX)
2218 
2219 DO_SHRNB(sve2_uqshrnb_h, uint16_t, uint8_t, DO_UQSHRN_H)
2220 DO_SHRNB(sve2_uqshrnb_s, uint32_t, uint16_t, DO_UQSHRN_S)
2221 DO_SHRNB(sve2_uqshrnb_d, uint64_t, uint32_t, DO_UQSHRN_D)
2222 
2223 DO_SHRNT(sve2_uqshrnt_h, uint16_t, uint8_t, H1_2, H1, DO_UQSHRN_H)
2224 DO_SHRNT(sve2_uqshrnt_s, uint32_t, uint16_t, H1_4, H1_2, DO_UQSHRN_S)
2225 DO_SHRNT(sve2_uqshrnt_d, uint64_t, uint32_t, H1_8, H1_4, DO_UQSHRN_D)
2226 
2227 #define DO_UQRSHRN_H(x, sh) MIN(do_urshr(x, sh), UINT8_MAX)
2228 #define DO_UQRSHRN_S(x, sh) MIN(do_urshr(x, sh), UINT16_MAX)
2229 #define DO_UQRSHRN_D(x, sh) MIN(do_urshr(x, sh), UINT32_MAX)
2230 
2231 DO_SHRNB(sve2_uqrshrnb_h, uint16_t, uint8_t, DO_UQRSHRN_H)
2232 DO_SHRNB(sve2_uqrshrnb_s, uint32_t, uint16_t, DO_UQRSHRN_S)
2233 DO_SHRNB(sve2_uqrshrnb_d, uint64_t, uint32_t, DO_UQRSHRN_D)
2234 
2235 DO_SHRNT(sve2_uqrshrnt_h, uint16_t, uint8_t, H1_2, H1, DO_UQRSHRN_H)
2236 DO_SHRNT(sve2_uqrshrnt_s, uint32_t, uint16_t, H1_4, H1_2, DO_UQRSHRN_S)
2237 DO_SHRNT(sve2_uqrshrnt_d, uint64_t, uint32_t, H1_8, H1_4, DO_UQRSHRN_D)
2238 
2239 #undef DO_SHRNB
2240 #undef DO_SHRNT
2241 
2242 #define DO_BINOPNB(NAME, TYPEW, TYPEN, SHIFT, OP)                           \
2243 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)              \
2244 {                                                                           \
2245     intptr_t i, opr_sz = simd_oprsz(desc);                                  \
2246     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {                           \
2247         TYPEW nn = *(TYPEW *)(vn + i);                                      \
2248         TYPEW mm = *(TYPEW *)(vm + i);                                      \
2249         *(TYPEW *)(vd + i) = (TYPEN)OP(nn, mm, SHIFT);                      \
2250     }                                                                       \
2251 }
2252 
2253 #define DO_BINOPNT(NAME, TYPEW, TYPEN, SHIFT, HW, HN, OP)                   \
2254 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)              \
2255 {                                                                           \
2256     intptr_t i, opr_sz = simd_oprsz(desc);                                  \
2257     for (i = 0; i < opr_sz; i += sizeof(TYPEW)) {                           \
2258         TYPEW nn = *(TYPEW *)(vn + HW(i));                                  \
2259         TYPEW mm = *(TYPEW *)(vm + HW(i));                                  \
2260         *(TYPEN *)(vd + HN(i + sizeof(TYPEN))) = OP(nn, mm, SHIFT);         \
2261     }                                                                       \
2262 }
2263 
2264 #define DO_ADDHN(N, M, SH)  ((N + M) >> SH)
2265 #define DO_RADDHN(N, M, SH) ((N + M + ((__typeof(N))1 << (SH - 1))) >> SH)
2266 #define DO_SUBHN(N, M, SH)  ((N - M) >> SH)
2267 #define DO_RSUBHN(N, M, SH) ((N - M + ((__typeof(N))1 << (SH - 1))) >> SH)
2268 
2269 DO_BINOPNB(sve2_addhnb_h, uint16_t, uint8_t, 8, DO_ADDHN)
2270 DO_BINOPNB(sve2_addhnb_s, uint32_t, uint16_t, 16, DO_ADDHN)
2271 DO_BINOPNB(sve2_addhnb_d, uint64_t, uint32_t, 32, DO_ADDHN)
2272 
2273 DO_BINOPNT(sve2_addhnt_h, uint16_t, uint8_t, 8, H1_2, H1, DO_ADDHN)
2274 DO_BINOPNT(sve2_addhnt_s, uint32_t, uint16_t, 16, H1_4, H1_2, DO_ADDHN)
2275 DO_BINOPNT(sve2_addhnt_d, uint64_t, uint32_t, 32, H1_8, H1_4, DO_ADDHN)
2276 
2277 DO_BINOPNB(sve2_raddhnb_h, uint16_t, uint8_t, 8, DO_RADDHN)
2278 DO_BINOPNB(sve2_raddhnb_s, uint32_t, uint16_t, 16, DO_RADDHN)
2279 DO_BINOPNB(sve2_raddhnb_d, uint64_t, uint32_t, 32, DO_RADDHN)
2280 
2281 DO_BINOPNT(sve2_raddhnt_h, uint16_t, uint8_t, 8, H1_2, H1, DO_RADDHN)
2282 DO_BINOPNT(sve2_raddhnt_s, uint32_t, uint16_t, 16, H1_4, H1_2, DO_RADDHN)
2283 DO_BINOPNT(sve2_raddhnt_d, uint64_t, uint32_t, 32, H1_8, H1_4, DO_RADDHN)
2284 
2285 DO_BINOPNB(sve2_subhnb_h, uint16_t, uint8_t, 8, DO_SUBHN)
2286 DO_BINOPNB(sve2_subhnb_s, uint32_t, uint16_t, 16, DO_SUBHN)
2287 DO_BINOPNB(sve2_subhnb_d, uint64_t, uint32_t, 32, DO_SUBHN)
2288 
2289 DO_BINOPNT(sve2_subhnt_h, uint16_t, uint8_t, 8, H1_2, H1, DO_SUBHN)
2290 DO_BINOPNT(sve2_subhnt_s, uint32_t, uint16_t, 16, H1_4, H1_2, DO_SUBHN)
2291 DO_BINOPNT(sve2_subhnt_d, uint64_t, uint32_t, 32, H1_8, H1_4, DO_SUBHN)
2292 
2293 DO_BINOPNB(sve2_rsubhnb_h, uint16_t, uint8_t, 8, DO_RSUBHN)
2294 DO_BINOPNB(sve2_rsubhnb_s, uint32_t, uint16_t, 16, DO_RSUBHN)
2295 DO_BINOPNB(sve2_rsubhnb_d, uint64_t, uint32_t, 32, DO_RSUBHN)
2296 
2297 DO_BINOPNT(sve2_rsubhnt_h, uint16_t, uint8_t, 8, H1_2, H1, DO_RSUBHN)
2298 DO_BINOPNT(sve2_rsubhnt_s, uint32_t, uint16_t, 16, H1_4, H1_2, DO_RSUBHN)
2299 DO_BINOPNT(sve2_rsubhnt_d, uint64_t, uint32_t, 32, H1_8, H1_4, DO_RSUBHN)
2300 
2301 #undef DO_RSUBHN
2302 #undef DO_SUBHN
2303 #undef DO_RADDHN
2304 #undef DO_ADDHN
2305 
2306 #undef DO_BINOPNB
2307 
2308 /* Fully general four-operand expander, controlled by a predicate.
2309  */
2310 #define DO_ZPZZZ(NAME, TYPE, H, OP)                           \
2311 void HELPER(NAME)(void *vd, void *va, void *vn, void *vm,     \
2312                   void *vg, uint32_t desc)                    \
2313 {                                                             \
2314     intptr_t i, opr_sz = simd_oprsz(desc);                    \
2315     for (i = 0; i < opr_sz; ) {                               \
2316         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));       \
2317         do {                                                  \
2318             if (pg & 1) {                                     \
2319                 TYPE nn = *(TYPE *)(vn + H(i));               \
2320                 TYPE mm = *(TYPE *)(vm + H(i));               \
2321                 TYPE aa = *(TYPE *)(va + H(i));               \
2322                 *(TYPE *)(vd + H(i)) = OP(aa, nn, mm);        \
2323             }                                                 \
2324             i += sizeof(TYPE), pg >>= sizeof(TYPE);           \
2325         } while (i & 15);                                     \
2326     }                                                         \
2327 }
2328 
2329 /* Similarly, specialized for 64-bit operands.  */
2330 #define DO_ZPZZZ_D(NAME, TYPE, OP)                            \
2331 void HELPER(NAME)(void *vd, void *va, void *vn, void *vm,     \
2332                   void *vg, uint32_t desc)                    \
2333 {                                                             \
2334     intptr_t i, opr_sz = simd_oprsz(desc) / 8;                \
2335     TYPE *d = vd, *a = va, *n = vn, *m = vm;                  \
2336     uint8_t *pg = vg;                                         \
2337     for (i = 0; i < opr_sz; i += 1) {                         \
2338         if (pg[H1(i)] & 1) {                                  \
2339             TYPE aa = a[i], nn = n[i], mm = m[i];             \
2340             d[i] = OP(aa, nn, mm);                            \
2341         }                                                     \
2342     }                                                         \
2343 }
2344 
2345 #define DO_MLA(A, N, M)  (A + N * M)
2346 #define DO_MLS(A, N, M)  (A - N * M)
2347 
2348 DO_ZPZZZ(sve_mla_b, uint8_t, H1, DO_MLA)
2349 DO_ZPZZZ(sve_mls_b, uint8_t, H1, DO_MLS)
2350 
2351 DO_ZPZZZ(sve_mla_h, uint16_t, H1_2, DO_MLA)
2352 DO_ZPZZZ(sve_mls_h, uint16_t, H1_2, DO_MLS)
2353 
2354 DO_ZPZZZ(sve_mla_s, uint32_t, H1_4, DO_MLA)
2355 DO_ZPZZZ(sve_mls_s, uint32_t, H1_4, DO_MLS)
2356 
2357 DO_ZPZZZ_D(sve_mla_d, uint64_t, DO_MLA)
2358 DO_ZPZZZ_D(sve_mls_d, uint64_t, DO_MLS)
2359 
2360 #undef DO_MLA
2361 #undef DO_MLS
2362 #undef DO_ZPZZZ
2363 #undef DO_ZPZZZ_D
2364 
2365 void HELPER(sve_index_b)(void *vd, uint32_t start,
2366                          uint32_t incr, uint32_t desc)
2367 {
2368     intptr_t i, opr_sz = simd_oprsz(desc);
2369     uint8_t *d = vd;
2370     for (i = 0; i < opr_sz; i += 1) {
2371         d[H1(i)] = start + i * incr;
2372     }
2373 }
2374 
2375 void HELPER(sve_index_h)(void *vd, uint32_t start,
2376                          uint32_t incr, uint32_t desc)
2377 {
2378     intptr_t i, opr_sz = simd_oprsz(desc) / 2;
2379     uint16_t *d = vd;
2380     for (i = 0; i < opr_sz; i += 1) {
2381         d[H2(i)] = start + i * incr;
2382     }
2383 }
2384 
2385 void HELPER(sve_index_s)(void *vd, uint32_t start,
2386                          uint32_t incr, uint32_t desc)
2387 {
2388     intptr_t i, opr_sz = simd_oprsz(desc) / 4;
2389     uint32_t *d = vd;
2390     for (i = 0; i < opr_sz; i += 1) {
2391         d[H4(i)] = start + i * incr;
2392     }
2393 }
2394 
2395 void HELPER(sve_index_d)(void *vd, uint64_t start,
2396                          uint64_t incr, uint32_t desc)
2397 {
2398     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2399     uint64_t *d = vd;
2400     for (i = 0; i < opr_sz; i += 1) {
2401         d[i] = start + i * incr;
2402     }
2403 }
2404 
2405 void HELPER(sve_adr_p32)(void *vd, void *vn, void *vm, uint32_t desc)
2406 {
2407     intptr_t i, opr_sz = simd_oprsz(desc) / 4;
2408     uint32_t sh = simd_data(desc);
2409     uint32_t *d = vd, *n = vn, *m = vm;
2410     for (i = 0; i < opr_sz; i += 1) {
2411         d[i] = n[i] + (m[i] << sh);
2412     }
2413 }
2414 
2415 void HELPER(sve_adr_p64)(void *vd, void *vn, void *vm, uint32_t desc)
2416 {
2417     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2418     uint64_t sh = simd_data(desc);
2419     uint64_t *d = vd, *n = vn, *m = vm;
2420     for (i = 0; i < opr_sz; i += 1) {
2421         d[i] = n[i] + (m[i] << sh);
2422     }
2423 }
2424 
2425 void HELPER(sve_adr_s32)(void *vd, void *vn, void *vm, uint32_t desc)
2426 {
2427     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2428     uint64_t sh = simd_data(desc);
2429     uint64_t *d = vd, *n = vn, *m = vm;
2430     for (i = 0; i < opr_sz; i += 1) {
2431         d[i] = n[i] + ((uint64_t)(int32_t)m[i] << sh);
2432     }
2433 }
2434 
2435 void HELPER(sve_adr_u32)(void *vd, void *vn, void *vm, uint32_t desc)
2436 {
2437     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2438     uint64_t sh = simd_data(desc);
2439     uint64_t *d = vd, *n = vn, *m = vm;
2440     for (i = 0; i < opr_sz; i += 1) {
2441         d[i] = n[i] + ((uint64_t)(uint32_t)m[i] << sh);
2442     }
2443 }
2444 
2445 void HELPER(sve_fexpa_h)(void *vd, void *vn, uint32_t desc)
2446 {
2447     /* These constants are cut-and-paste directly from the ARM pseudocode.  */
2448     static const uint16_t coeff[] = {
2449         0x0000, 0x0016, 0x002d, 0x0045, 0x005d, 0x0075, 0x008e, 0x00a8,
2450         0x00c2, 0x00dc, 0x00f8, 0x0114, 0x0130, 0x014d, 0x016b, 0x0189,
2451         0x01a8, 0x01c8, 0x01e8, 0x0209, 0x022b, 0x024e, 0x0271, 0x0295,
2452         0x02ba, 0x02e0, 0x0306, 0x032e, 0x0356, 0x037f, 0x03a9, 0x03d4,
2453     };
2454     intptr_t i, opr_sz = simd_oprsz(desc) / 2;
2455     uint16_t *d = vd, *n = vn;
2456 
2457     for (i = 0; i < opr_sz; i++) {
2458         uint16_t nn = n[i];
2459         intptr_t idx = extract32(nn, 0, 5);
2460         uint16_t exp = extract32(nn, 5, 5);
2461         d[i] = coeff[idx] | (exp << 10);
2462     }
2463 }
2464 
2465 void HELPER(sve_fexpa_s)(void *vd, void *vn, uint32_t desc)
2466 {
2467     /* These constants are cut-and-paste directly from the ARM pseudocode.  */
2468     static const uint32_t coeff[] = {
2469         0x000000, 0x0164d2, 0x02cd87, 0x043a29,
2470         0x05aac3, 0x071f62, 0x08980f, 0x0a14d5,
2471         0x0b95c2, 0x0d1adf, 0x0ea43a, 0x1031dc,
2472         0x11c3d3, 0x135a2b, 0x14f4f0, 0x16942d,
2473         0x1837f0, 0x19e046, 0x1b8d3a, 0x1d3eda,
2474         0x1ef532, 0x20b051, 0x227043, 0x243516,
2475         0x25fed7, 0x27cd94, 0x29a15b, 0x2b7a3a,
2476         0x2d583f, 0x2f3b79, 0x3123f6, 0x3311c4,
2477         0x3504f3, 0x36fd92, 0x38fbaf, 0x3aff5b,
2478         0x3d08a4, 0x3f179a, 0x412c4d, 0x4346cd,
2479         0x45672a, 0x478d75, 0x49b9be, 0x4bec15,
2480         0x4e248c, 0x506334, 0x52a81e, 0x54f35b,
2481         0x5744fd, 0x599d16, 0x5bfbb8, 0x5e60f5,
2482         0x60ccdf, 0x633f89, 0x65b907, 0x68396a,
2483         0x6ac0c7, 0x6d4f30, 0x6fe4ba, 0x728177,
2484         0x75257d, 0x77d0df, 0x7a83b3, 0x7d3e0c,
2485     };
2486     intptr_t i, opr_sz = simd_oprsz(desc) / 4;
2487     uint32_t *d = vd, *n = vn;
2488 
2489     for (i = 0; i < opr_sz; i++) {
2490         uint32_t nn = n[i];
2491         intptr_t idx = extract32(nn, 0, 6);
2492         uint32_t exp = extract32(nn, 6, 8);
2493         d[i] = coeff[idx] | (exp << 23);
2494     }
2495 }
2496 
2497 void HELPER(sve_fexpa_d)(void *vd, void *vn, uint32_t desc)
2498 {
2499     /* These constants are cut-and-paste directly from the ARM pseudocode.  */
2500     static const uint64_t coeff[] = {
2501         0x0000000000000ull, 0x02C9A3E778061ull, 0x059B0D3158574ull,
2502         0x0874518759BC8ull, 0x0B5586CF9890Full, 0x0E3EC32D3D1A2ull,
2503         0x11301D0125B51ull, 0x1429AAEA92DE0ull, 0x172B83C7D517Bull,
2504         0x1A35BEB6FCB75ull, 0x1D4873168B9AAull, 0x2063B88628CD6ull,
2505         0x2387A6E756238ull, 0x26B4565E27CDDull, 0x29E9DF51FDEE1ull,
2506         0x2D285A6E4030Bull, 0x306FE0A31B715ull, 0x33C08B26416FFull,
2507         0x371A7373AA9CBull, 0x3A7DB34E59FF7ull, 0x3DEA64C123422ull,
2508         0x4160A21F72E2Aull, 0x44E086061892Dull, 0x486A2B5C13CD0ull,
2509         0x4BFDAD5362A27ull, 0x4F9B2769D2CA7ull, 0x5342B569D4F82ull,
2510         0x56F4736B527DAull, 0x5AB07DD485429ull, 0x5E76F15AD2148ull,
2511         0x6247EB03A5585ull, 0x6623882552225ull, 0x6A09E667F3BCDull,
2512         0x6DFB23C651A2Full, 0x71F75E8EC5F74ull, 0x75FEB564267C9ull,
2513         0x7A11473EB0187ull, 0x7E2F336CF4E62ull, 0x82589994CCE13ull,
2514         0x868D99B4492EDull, 0x8ACE5422AA0DBull, 0x8F1AE99157736ull,
2515         0x93737B0CDC5E5ull, 0x97D829FDE4E50ull, 0x9C49182A3F090ull,
2516         0xA0C667B5DE565ull, 0xA5503B23E255Dull, 0xA9E6B5579FDBFull,
2517         0xAE89F995AD3ADull, 0xB33A2B84F15FBull, 0xB7F76F2FB5E47ull,
2518         0xBCC1E904BC1D2ull, 0xC199BDD85529Cull, 0xC67F12E57D14Bull,
2519         0xCB720DCEF9069ull, 0xD072D4A07897Cull, 0xD5818DCFBA487ull,
2520         0xDA9E603DB3285ull, 0xDFC97337B9B5Full, 0xE502EE78B3FF6ull,
2521         0xEA4AFA2A490DAull, 0xEFA1BEE615A27ull, 0xF50765B6E4540ull,
2522         0xFA7C1819E90D8ull,
2523     };
2524     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2525     uint64_t *d = vd, *n = vn;
2526 
2527     for (i = 0; i < opr_sz; i++) {
2528         uint64_t nn = n[i];
2529         intptr_t idx = extract32(nn, 0, 6);
2530         uint64_t exp = extract32(nn, 6, 11);
2531         d[i] = coeff[idx] | (exp << 52);
2532     }
2533 }
2534 
2535 void HELPER(sve_ftssel_h)(void *vd, void *vn, void *vm, uint32_t desc)
2536 {
2537     intptr_t i, opr_sz = simd_oprsz(desc) / 2;
2538     uint16_t *d = vd, *n = vn, *m = vm;
2539     for (i = 0; i < opr_sz; i += 1) {
2540         uint16_t nn = n[i];
2541         uint16_t mm = m[i];
2542         if (mm & 1) {
2543             nn = float16_one;
2544         }
2545         d[i] = nn ^ (mm & 2) << 14;
2546     }
2547 }
2548 
2549 void HELPER(sve_ftssel_s)(void *vd, void *vn, void *vm, uint32_t desc)
2550 {
2551     intptr_t i, opr_sz = simd_oprsz(desc) / 4;
2552     uint32_t *d = vd, *n = vn, *m = vm;
2553     for (i = 0; i < opr_sz; i += 1) {
2554         uint32_t nn = n[i];
2555         uint32_t mm = m[i];
2556         if (mm & 1) {
2557             nn = float32_one;
2558         }
2559         d[i] = nn ^ (mm & 2) << 30;
2560     }
2561 }
2562 
2563 void HELPER(sve_ftssel_d)(void *vd, void *vn, void *vm, uint32_t desc)
2564 {
2565     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2566     uint64_t *d = vd, *n = vn, *m = vm;
2567     for (i = 0; i < opr_sz; i += 1) {
2568         uint64_t nn = n[i];
2569         uint64_t mm = m[i];
2570         if (mm & 1) {
2571             nn = float64_one;
2572         }
2573         d[i] = nn ^ (mm & 2) << 62;
2574     }
2575 }
2576 
2577 /*
2578  * Signed saturating addition with scalar operand.
2579  */
2580 
2581 void HELPER(sve_sqaddi_b)(void *d, void *a, int32_t b, uint32_t desc)
2582 {
2583     intptr_t i, oprsz = simd_oprsz(desc);
2584 
2585     for (i = 0; i < oprsz; i += sizeof(int8_t)) {
2586         *(int8_t *)(d + i) = DO_SQADD_B(b, *(int8_t *)(a + i));
2587     }
2588 }
2589 
2590 void HELPER(sve_sqaddi_h)(void *d, void *a, int32_t b, uint32_t desc)
2591 {
2592     intptr_t i, oprsz = simd_oprsz(desc);
2593 
2594     for (i = 0; i < oprsz; i += sizeof(int16_t)) {
2595         *(int16_t *)(d + i) = DO_SQADD_H(b, *(int16_t *)(a + i));
2596     }
2597 }
2598 
2599 void HELPER(sve_sqaddi_s)(void *d, void *a, int64_t b, uint32_t desc)
2600 {
2601     intptr_t i, oprsz = simd_oprsz(desc);
2602 
2603     for (i = 0; i < oprsz; i += sizeof(int32_t)) {
2604         *(int32_t *)(d + i) = DO_SQADD_S(b, *(int32_t *)(a + i));
2605     }
2606 }
2607 
2608 void HELPER(sve_sqaddi_d)(void *d, void *a, int64_t b, uint32_t desc)
2609 {
2610     intptr_t i, oprsz = simd_oprsz(desc);
2611 
2612     for (i = 0; i < oprsz; i += sizeof(int64_t)) {
2613         *(int64_t *)(d + i) = do_sqadd_d(b, *(int64_t *)(a + i));
2614     }
2615 }
2616 
2617 /*
2618  * Unsigned saturating addition with scalar operand.
2619  */
2620 
2621 void HELPER(sve_uqaddi_b)(void *d, void *a, int32_t b, uint32_t desc)
2622 {
2623     intptr_t i, oprsz = simd_oprsz(desc);
2624 
2625     for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
2626         *(uint8_t *)(d + i) = DO_UQADD_B(b, *(uint8_t *)(a + i));
2627     }
2628 }
2629 
2630 void HELPER(sve_uqaddi_h)(void *d, void *a, int32_t b, uint32_t desc)
2631 {
2632     intptr_t i, oprsz = simd_oprsz(desc);
2633 
2634     for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
2635         *(uint16_t *)(d + i) = DO_UQADD_H(b, *(uint16_t *)(a + i));
2636     }
2637 }
2638 
2639 void HELPER(sve_uqaddi_s)(void *d, void *a, int64_t b, uint32_t desc)
2640 {
2641     intptr_t i, oprsz = simd_oprsz(desc);
2642 
2643     for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
2644         *(uint32_t *)(d + i) = DO_UQADD_S(b, *(uint32_t *)(a + i));
2645     }
2646 }
2647 
2648 void HELPER(sve_uqaddi_d)(void *d, void *a, uint64_t b, uint32_t desc)
2649 {
2650     intptr_t i, oprsz = simd_oprsz(desc);
2651 
2652     for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
2653         *(uint64_t *)(d + i) = do_uqadd_d(b, *(uint64_t *)(a + i));
2654     }
2655 }
2656 
2657 void HELPER(sve_uqsubi_d)(void *d, void *a, uint64_t b, uint32_t desc)
2658 {
2659     intptr_t i, oprsz = simd_oprsz(desc);
2660 
2661     for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
2662         *(uint64_t *)(d + i) = do_uqsub_d(*(uint64_t *)(a + i), b);
2663     }
2664 }
2665 
2666 /* Two operand predicated copy immediate with merge.  All valid immediates
2667  * can fit within 17 signed bits in the simd_data field.
2668  */
2669 void HELPER(sve_cpy_m_b)(void *vd, void *vn, void *vg,
2670                          uint64_t mm, uint32_t desc)
2671 {
2672     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2673     uint64_t *d = vd, *n = vn;
2674     uint8_t *pg = vg;
2675 
2676     mm = dup_const(MO_8, mm);
2677     for (i = 0; i < opr_sz; i += 1) {
2678         uint64_t nn = n[i];
2679         uint64_t pp = expand_pred_b(pg[H1(i)]);
2680         d[i] = (mm & pp) | (nn & ~pp);
2681     }
2682 }
2683 
2684 void HELPER(sve_cpy_m_h)(void *vd, void *vn, void *vg,
2685                          uint64_t mm, uint32_t desc)
2686 {
2687     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2688     uint64_t *d = vd, *n = vn;
2689     uint8_t *pg = vg;
2690 
2691     mm = dup_const(MO_16, mm);
2692     for (i = 0; i < opr_sz; i += 1) {
2693         uint64_t nn = n[i];
2694         uint64_t pp = expand_pred_h(pg[H1(i)]);
2695         d[i] = (mm & pp) | (nn & ~pp);
2696     }
2697 }
2698 
2699 void HELPER(sve_cpy_m_s)(void *vd, void *vn, void *vg,
2700                          uint64_t mm, uint32_t desc)
2701 {
2702     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2703     uint64_t *d = vd, *n = vn;
2704     uint8_t *pg = vg;
2705 
2706     mm = dup_const(MO_32, mm);
2707     for (i = 0; i < opr_sz; i += 1) {
2708         uint64_t nn = n[i];
2709         uint64_t pp = expand_pred_s(pg[H1(i)]);
2710         d[i] = (mm & pp) | (nn & ~pp);
2711     }
2712 }
2713 
2714 void HELPER(sve_cpy_m_d)(void *vd, void *vn, void *vg,
2715                          uint64_t mm, uint32_t desc)
2716 {
2717     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2718     uint64_t *d = vd, *n = vn;
2719     uint8_t *pg = vg;
2720 
2721     for (i = 0; i < opr_sz; i += 1) {
2722         uint64_t nn = n[i];
2723         d[i] = (pg[H1(i)] & 1 ? mm : nn);
2724     }
2725 }
2726 
2727 void HELPER(sve_cpy_z_b)(void *vd, void *vg, uint64_t val, uint32_t desc)
2728 {
2729     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2730     uint64_t *d = vd;
2731     uint8_t *pg = vg;
2732 
2733     val = dup_const(MO_8, val);
2734     for (i = 0; i < opr_sz; i += 1) {
2735         d[i] = val & expand_pred_b(pg[H1(i)]);
2736     }
2737 }
2738 
2739 void HELPER(sve_cpy_z_h)(void *vd, void *vg, uint64_t val, uint32_t desc)
2740 {
2741     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2742     uint64_t *d = vd;
2743     uint8_t *pg = vg;
2744 
2745     val = dup_const(MO_16, val);
2746     for (i = 0; i < opr_sz; i += 1) {
2747         d[i] = val & expand_pred_h(pg[H1(i)]);
2748     }
2749 }
2750 
2751 void HELPER(sve_cpy_z_s)(void *vd, void *vg, uint64_t val, uint32_t desc)
2752 {
2753     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2754     uint64_t *d = vd;
2755     uint8_t *pg = vg;
2756 
2757     val = dup_const(MO_32, val);
2758     for (i = 0; i < opr_sz; i += 1) {
2759         d[i] = val & expand_pred_s(pg[H1(i)]);
2760     }
2761 }
2762 
2763 void HELPER(sve_cpy_z_d)(void *vd, void *vg, uint64_t val, uint32_t desc)
2764 {
2765     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
2766     uint64_t *d = vd;
2767     uint8_t *pg = vg;
2768 
2769     for (i = 0; i < opr_sz; i += 1) {
2770         d[i] = (pg[H1(i)] & 1 ? val : 0);
2771     }
2772 }
2773 
2774 /* Big-endian hosts need to frob the byte indices.  If the copy
2775  * happens to be 8-byte aligned, then no frobbing necessary.
2776  */
2777 static void swap_memmove(void *vd, void *vs, size_t n)
2778 {
2779     uintptr_t d = (uintptr_t)vd;
2780     uintptr_t s = (uintptr_t)vs;
2781     uintptr_t o = (d | s | n) & 7;
2782     size_t i;
2783 
2784 #if !HOST_BIG_ENDIAN
2785     o = 0;
2786 #endif
2787     switch (o) {
2788     case 0:
2789         memmove(vd, vs, n);
2790         break;
2791 
2792     case 4:
2793         if (d < s || d >= s + n) {
2794             for (i = 0; i < n; i += 4) {
2795                 *(uint32_t *)H1_4(d + i) = *(uint32_t *)H1_4(s + i);
2796             }
2797         } else {
2798             for (i = n; i > 0; ) {
2799                 i -= 4;
2800                 *(uint32_t *)H1_4(d + i) = *(uint32_t *)H1_4(s + i);
2801             }
2802         }
2803         break;
2804 
2805     case 2:
2806     case 6:
2807         if (d < s || d >= s + n) {
2808             for (i = 0; i < n; i += 2) {
2809                 *(uint16_t *)H1_2(d + i) = *(uint16_t *)H1_2(s + i);
2810             }
2811         } else {
2812             for (i = n; i > 0; ) {
2813                 i -= 2;
2814                 *(uint16_t *)H1_2(d + i) = *(uint16_t *)H1_2(s + i);
2815             }
2816         }
2817         break;
2818 
2819     default:
2820         if (d < s || d >= s + n) {
2821             for (i = 0; i < n; i++) {
2822                 *(uint8_t *)H1(d + i) = *(uint8_t *)H1(s + i);
2823             }
2824         } else {
2825             for (i = n; i > 0; ) {
2826                 i -= 1;
2827                 *(uint8_t *)H1(d + i) = *(uint8_t *)H1(s + i);
2828             }
2829         }
2830         break;
2831     }
2832 }
2833 
2834 /* Similarly for memset of 0.  */
2835 static void swap_memzero(void *vd, size_t n)
2836 {
2837     uintptr_t d = (uintptr_t)vd;
2838     uintptr_t o = (d | n) & 7;
2839     size_t i;
2840 
2841     /* Usually, the first bit of a predicate is set, so N is 0.  */
2842     if (likely(n == 0)) {
2843         return;
2844     }
2845 
2846 #if !HOST_BIG_ENDIAN
2847     o = 0;
2848 #endif
2849     switch (o) {
2850     case 0:
2851         memset(vd, 0, n);
2852         break;
2853 
2854     case 4:
2855         for (i = 0; i < n; i += 4) {
2856             *(uint32_t *)H1_4(d + i) = 0;
2857         }
2858         break;
2859 
2860     case 2:
2861     case 6:
2862         for (i = 0; i < n; i += 2) {
2863             *(uint16_t *)H1_2(d + i) = 0;
2864         }
2865         break;
2866 
2867     default:
2868         for (i = 0; i < n; i++) {
2869             *(uint8_t *)H1(d + i) = 0;
2870         }
2871         break;
2872     }
2873 }
2874 
2875 void HELPER(sve_ext)(void *vd, void *vn, void *vm, uint32_t desc)
2876 {
2877     intptr_t opr_sz = simd_oprsz(desc);
2878     size_t n_ofs = simd_data(desc);
2879     size_t n_siz = opr_sz - n_ofs;
2880 
2881     if (vd != vm) {
2882         swap_memmove(vd, vn + n_ofs, n_siz);
2883         swap_memmove(vd + n_siz, vm, n_ofs);
2884     } else if (vd != vn) {
2885         swap_memmove(vd + n_siz, vd, n_ofs);
2886         swap_memmove(vd, vn + n_ofs, n_siz);
2887     } else {
2888         /* vd == vn == vm.  Need temp space.  */
2889         ARMVectorReg tmp;
2890         swap_memmove(&tmp, vm, n_ofs);
2891         swap_memmove(vd, vd + n_ofs, n_siz);
2892         memcpy(vd + n_siz, &tmp, n_ofs);
2893     }
2894 }
2895 
2896 #define DO_INSR(NAME, TYPE, H) \
2897 void HELPER(NAME)(void *vd, void *vn, uint64_t val, uint32_t desc) \
2898 {                                                                  \
2899     intptr_t opr_sz = simd_oprsz(desc);                            \
2900     swap_memmove(vd + sizeof(TYPE), vn, opr_sz - sizeof(TYPE));    \
2901     *(TYPE *)(vd + H(0)) = val;                                    \
2902 }
2903 
2904 DO_INSR(sve_insr_b, uint8_t, H1)
2905 DO_INSR(sve_insr_h, uint16_t, H1_2)
2906 DO_INSR(sve_insr_s, uint32_t, H1_4)
2907 DO_INSR(sve_insr_d, uint64_t, H1_8)
2908 
2909 #undef DO_INSR
2910 
2911 void HELPER(sve_rev_b)(void *vd, void *vn, uint32_t desc)
2912 {
2913     intptr_t i, j, opr_sz = simd_oprsz(desc);
2914     for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
2915         uint64_t f = *(uint64_t *)(vn + i);
2916         uint64_t b = *(uint64_t *)(vn + j);
2917         *(uint64_t *)(vd + i) = bswap64(b);
2918         *(uint64_t *)(vd + j) = bswap64(f);
2919     }
2920 }
2921 
2922 void HELPER(sve_rev_h)(void *vd, void *vn, uint32_t desc)
2923 {
2924     intptr_t i, j, opr_sz = simd_oprsz(desc);
2925     for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
2926         uint64_t f = *(uint64_t *)(vn + i);
2927         uint64_t b = *(uint64_t *)(vn + j);
2928         *(uint64_t *)(vd + i) = hswap64(b);
2929         *(uint64_t *)(vd + j) = hswap64(f);
2930     }
2931 }
2932 
2933 void HELPER(sve_rev_s)(void *vd, void *vn, uint32_t desc)
2934 {
2935     intptr_t i, j, opr_sz = simd_oprsz(desc);
2936     for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
2937         uint64_t f = *(uint64_t *)(vn + i);
2938         uint64_t b = *(uint64_t *)(vn + j);
2939         *(uint64_t *)(vd + i) = rol64(b, 32);
2940         *(uint64_t *)(vd + j) = rol64(f, 32);
2941     }
2942 }
2943 
2944 void HELPER(sve_rev_d)(void *vd, void *vn, uint32_t desc)
2945 {
2946     intptr_t i, j, opr_sz = simd_oprsz(desc);
2947     for (i = 0, j = opr_sz - 8; i < opr_sz / 2; i += 8, j -= 8) {
2948         uint64_t f = *(uint64_t *)(vn + i);
2949         uint64_t b = *(uint64_t *)(vn + j);
2950         *(uint64_t *)(vd + i) = b;
2951         *(uint64_t *)(vd + j) = f;
2952     }
2953 }
2954 
2955 typedef void tb_impl_fn(void *, void *, void *, void *, uintptr_t, bool);
2956 
2957 static inline void do_tbl1(void *vd, void *vn, void *vm, uint32_t desc,
2958                            bool is_tbx, tb_impl_fn *fn)
2959 {
2960     ARMVectorReg scratch;
2961     uintptr_t oprsz = simd_oprsz(desc);
2962 
2963     if (unlikely(vd == vn)) {
2964         vn = memcpy(&scratch, vn, oprsz);
2965     }
2966 
2967     fn(vd, vn, NULL, vm, oprsz, is_tbx);
2968 }
2969 
2970 static inline void do_tbl2(void *vd, void *vn0, void *vn1, void *vm,
2971                            uint32_t desc, bool is_tbx, tb_impl_fn *fn)
2972 {
2973     ARMVectorReg scratch;
2974     uintptr_t oprsz = simd_oprsz(desc);
2975 
2976     if (unlikely(vd == vn0)) {
2977         vn0 = memcpy(&scratch, vn0, oprsz);
2978         if (vd == vn1) {
2979             vn1 = vn0;
2980         }
2981     } else if (unlikely(vd == vn1)) {
2982         vn1 = memcpy(&scratch, vn1, oprsz);
2983     }
2984 
2985     fn(vd, vn0, vn1, vm, oprsz, is_tbx);
2986 }
2987 
2988 #define DO_TB(SUFF, TYPE, H)                                            \
2989 static inline void do_tb_##SUFF(void *vd, void *vt0, void *vt1,         \
2990                                 void *vm, uintptr_t oprsz, bool is_tbx) \
2991 {                                                                       \
2992     TYPE *d = vd, *tbl0 = vt0, *tbl1 = vt1, *indexes = vm;              \
2993     uintptr_t i, nelem = oprsz / sizeof(TYPE);                          \
2994     for (i = 0; i < nelem; ++i) {                                       \
2995         TYPE index = indexes[H1(i)], val = 0;                           \
2996         if (index < nelem) {                                            \
2997             val = tbl0[H(index)];                                       \
2998         } else {                                                        \
2999             index -= nelem;                                             \
3000             if (tbl1 && index < nelem) {                                \
3001                 val = tbl1[H(index)];                                   \
3002             } else if (is_tbx) {                                        \
3003                 continue;                                               \
3004             }                                                           \
3005         }                                                               \
3006         d[H(i)] = val;                                                  \
3007     }                                                                   \
3008 }                                                                       \
3009 void HELPER(sve_tbl_##SUFF)(void *vd, void *vn, void *vm, uint32_t desc) \
3010 {                                                                       \
3011     do_tbl1(vd, vn, vm, desc, false, do_tb_##SUFF);                     \
3012 }                                                                       \
3013 void HELPER(sve2_tbl_##SUFF)(void *vd, void *vn0, void *vn1,            \
3014                              void *vm, uint32_t desc)                   \
3015 {                                                                       \
3016     do_tbl2(vd, vn0, vn1, vm, desc, false, do_tb_##SUFF);               \
3017 }                                                                       \
3018 void HELPER(sve2_tbx_##SUFF)(void *vd, void *vn, void *vm, uint32_t desc) \
3019 {                                                                       \
3020     do_tbl1(vd, vn, vm, desc, true, do_tb_##SUFF);                      \
3021 }
3022 
3023 DO_TB(b, uint8_t, H1)
3024 DO_TB(h, uint16_t, H2)
3025 DO_TB(s, uint32_t, H4)
3026 DO_TB(d, uint64_t, H8)
3027 
3028 #undef DO_TB
3029 
3030 #define DO_UNPK(NAME, TYPED, TYPES, HD, HS) \
3031 void HELPER(NAME)(void *vd, void *vn, uint32_t desc)           \
3032 {                                                              \
3033     intptr_t i, opr_sz = simd_oprsz(desc);                     \
3034     TYPED *d = vd;                                             \
3035     TYPES *n = vn;                                             \
3036     ARMVectorReg tmp;                                          \
3037     if (unlikely(vn - vd < opr_sz)) {                          \
3038         n = memcpy(&tmp, n, opr_sz / 2);                       \
3039     }                                                          \
3040     for (i = 0; i < opr_sz / sizeof(TYPED); i++) {             \
3041         d[HD(i)] = n[HS(i)];                                   \
3042     }                                                          \
3043 }
3044 
3045 DO_UNPK(sve_sunpk_h, int16_t, int8_t, H2, H1)
3046 DO_UNPK(sve_sunpk_s, int32_t, int16_t, H4, H2)
3047 DO_UNPK(sve_sunpk_d, int64_t, int32_t, H8, H4)
3048 
3049 DO_UNPK(sve_uunpk_h, uint16_t, uint8_t, H2, H1)
3050 DO_UNPK(sve_uunpk_s, uint32_t, uint16_t, H4, H2)
3051 DO_UNPK(sve_uunpk_d, uint64_t, uint32_t, H8, H4)
3052 
3053 #undef DO_UNPK
3054 
3055 /* Mask of bits included in the even numbered predicates of width esz.
3056  * We also use this for expand_bits/compress_bits, and so extend the
3057  * same pattern out to 16-bit units.
3058  */
3059 static const uint64_t even_bit_esz_masks[5] = {
3060     0x5555555555555555ull,
3061     0x3333333333333333ull,
3062     0x0f0f0f0f0f0f0f0full,
3063     0x00ff00ff00ff00ffull,
3064     0x0000ffff0000ffffull,
3065 };
3066 
3067 /* Zero-extend units of 2**N bits to units of 2**(N+1) bits.
3068  * For N==0, this corresponds to the operation that in qemu/bitops.h
3069  * we call half_shuffle64; this algorithm is from Hacker's Delight,
3070  * section 7-2 Shuffling Bits.
3071  */
3072 static uint64_t expand_bits(uint64_t x, int n)
3073 {
3074     int i;
3075 
3076     x &= 0xffffffffu;
3077     for (i = 4; i >= n; i--) {
3078         int sh = 1 << i;
3079         x = ((x << sh) | x) & even_bit_esz_masks[i];
3080     }
3081     return x;
3082 }
3083 
3084 /* Compress units of 2**(N+1) bits to units of 2**N bits.
3085  * For N==0, this corresponds to the operation that in qemu/bitops.h
3086  * we call half_unshuffle64; this algorithm is from Hacker's Delight,
3087  * section 7-2 Shuffling Bits, where it is called an inverse half shuffle.
3088  */
3089 static uint64_t compress_bits(uint64_t x, int n)
3090 {
3091     int i;
3092 
3093     for (i = n; i <= 4; i++) {
3094         int sh = 1 << i;
3095         x &= even_bit_esz_masks[i];
3096         x = (x >> sh) | x;
3097     }
3098     return x & 0xffffffffu;
3099 }
3100 
3101 void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
3102 {
3103     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3104     int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
3105     intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
3106     int esize = 1 << esz;
3107     uint64_t *d = vd;
3108     intptr_t i;
3109 
3110     if (oprsz <= 8) {
3111         uint64_t nn = *(uint64_t *)vn;
3112         uint64_t mm = *(uint64_t *)vm;
3113         int half = 4 * oprsz;
3114 
3115         nn = extract64(nn, high * half, half);
3116         mm = extract64(mm, high * half, half);
3117         nn = expand_bits(nn, esz);
3118         mm = expand_bits(mm, esz);
3119         d[0] = nn | (mm << esize);
3120     } else {
3121         ARMPredicateReg tmp;
3122 
3123         /* We produce output faster than we consume input.
3124            Therefore we must be mindful of possible overlap.  */
3125         if (vd == vn) {
3126             vn = memcpy(&tmp, vn, oprsz);
3127             if (vd == vm) {
3128                 vm = vn;
3129             }
3130         } else if (vd == vm) {
3131             vm = memcpy(&tmp, vm, oprsz);
3132         }
3133         if (high) {
3134             high = oprsz >> 1;
3135         }
3136 
3137         if ((oprsz & 7) == 0) {
3138             uint32_t *n = vn, *m = vm;
3139             high >>= 2;
3140 
3141             for (i = 0; i < oprsz / 8; i++) {
3142                 uint64_t nn = n[H4(high + i)];
3143                 uint64_t mm = m[H4(high + i)];
3144 
3145                 nn = expand_bits(nn, esz);
3146                 mm = expand_bits(mm, esz);
3147                 d[i] = nn | (mm << esize);
3148             }
3149         } else {
3150             uint8_t *n = vn, *m = vm;
3151             uint16_t *d16 = vd;
3152 
3153             for (i = 0; i < oprsz / 2; i++) {
3154                 uint16_t nn = n[H1(high + i)];
3155                 uint16_t mm = m[H1(high + i)];
3156 
3157                 nn = expand_bits(nn, esz);
3158                 mm = expand_bits(mm, esz);
3159                 d16[H2(i)] = nn | (mm << esize);
3160             }
3161         }
3162     }
3163 }
3164 
3165 void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
3166 {
3167     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3168     int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
3169     int odd = FIELD_EX32(pred_desc, PREDDESC, DATA) << esz;
3170     uint64_t *d = vd, *n = vn, *m = vm;
3171     uint64_t l, h;
3172     intptr_t i;
3173 
3174     if (oprsz <= 8) {
3175         l = compress_bits(n[0] >> odd, esz);
3176         h = compress_bits(m[0] >> odd, esz);
3177         d[0] = l | (h << (4 * oprsz));
3178     } else {
3179         ARMPredicateReg tmp_m;
3180         intptr_t oprsz_16 = oprsz / 16;
3181 
3182         if ((vm - vd) < (uintptr_t)oprsz) {
3183             m = memcpy(&tmp_m, vm, oprsz);
3184         }
3185 
3186         for (i = 0; i < oprsz_16; i++) {
3187             l = n[2 * i + 0];
3188             h = n[2 * i + 1];
3189             l = compress_bits(l >> odd, esz);
3190             h = compress_bits(h >> odd, esz);
3191             d[i] = l | (h << 32);
3192         }
3193 
3194         /*
3195          * For VL which is not a multiple of 512, the results from M do not
3196          * align nicely with the uint64_t for D.  Put the aligned results
3197          * from M into TMP_M and then copy it into place afterward.
3198          */
3199         if (oprsz & 15) {
3200             int final_shift = (oprsz & 15) * 2;
3201 
3202             l = n[2 * i + 0];
3203             h = n[2 * i + 1];
3204             l = compress_bits(l >> odd, esz);
3205             h = compress_bits(h >> odd, esz);
3206             d[i] = l | (h << final_shift);
3207 
3208             for (i = 0; i < oprsz_16; i++) {
3209                 l = m[2 * i + 0];
3210                 h = m[2 * i + 1];
3211                 l = compress_bits(l >> odd, esz);
3212                 h = compress_bits(h >> odd, esz);
3213                 tmp_m.p[i] = l | (h << 32);
3214             }
3215             l = m[2 * i + 0];
3216             h = m[2 * i + 1];
3217             l = compress_bits(l >> odd, esz);
3218             h = compress_bits(h >> odd, esz);
3219             tmp_m.p[i] = l | (h << final_shift);
3220 
3221             swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
3222         } else {
3223             for (i = 0; i < oprsz_16; i++) {
3224                 l = m[2 * i + 0];
3225                 h = m[2 * i + 1];
3226                 l = compress_bits(l >> odd, esz);
3227                 h = compress_bits(h >> odd, esz);
3228                 d[oprsz_16 + i] = l | (h << 32);
3229             }
3230         }
3231     }
3232 }
3233 
3234 void HELPER(sve_trn_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
3235 {
3236     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3237     int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
3238     int odd = FIELD_EX32(pred_desc, PREDDESC, DATA);
3239     uint64_t *d = vd, *n = vn, *m = vm;
3240     uint64_t mask;
3241     int shr, shl;
3242     intptr_t i;
3243 
3244     shl = 1 << esz;
3245     shr = 0;
3246     mask = even_bit_esz_masks[esz];
3247     if (odd) {
3248         mask <<= shl;
3249         shr = shl;
3250         shl = 0;
3251     }
3252 
3253     for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
3254         uint64_t nn = (n[i] & mask) >> shr;
3255         uint64_t mm = (m[i] & mask) << shl;
3256         d[i] = nn + mm;
3257     }
3258 }
3259 
3260 /* Reverse units of 2**N bits.  */
3261 static uint64_t reverse_bits_64(uint64_t x, int n)
3262 {
3263     int i, sh;
3264 
3265     x = bswap64(x);
3266     for (i = 2, sh = 4; i >= n; i--, sh >>= 1) {
3267         uint64_t mask = even_bit_esz_masks[i];
3268         x = ((x & mask) << sh) | ((x >> sh) & mask);
3269     }
3270     return x;
3271 }
3272 
3273 static uint8_t reverse_bits_8(uint8_t x, int n)
3274 {
3275     static const uint8_t mask[3] = { 0x55, 0x33, 0x0f };
3276     int i, sh;
3277 
3278     for (i = 2, sh = 4; i >= n; i--, sh >>= 1) {
3279         x = ((x & mask[i]) << sh) | ((x >> sh) & mask[i]);
3280     }
3281     return x;
3282 }
3283 
3284 void HELPER(sve_rev_p)(void *vd, void *vn, uint32_t pred_desc)
3285 {
3286     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3287     int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
3288     intptr_t i, oprsz_2 = oprsz / 2;
3289 
3290     if (oprsz <= 8) {
3291         uint64_t l = *(uint64_t *)vn;
3292         l = reverse_bits_64(l << (64 - 8 * oprsz), esz);
3293         *(uint64_t *)vd = l;
3294     } else if ((oprsz & 15) == 0) {
3295         for (i = 0; i < oprsz_2; i += 8) {
3296             intptr_t ih = oprsz - 8 - i;
3297             uint64_t l = reverse_bits_64(*(uint64_t *)(vn + i), esz);
3298             uint64_t h = reverse_bits_64(*(uint64_t *)(vn + ih), esz);
3299             *(uint64_t *)(vd + i) = h;
3300             *(uint64_t *)(vd + ih) = l;
3301         }
3302     } else {
3303         for (i = 0; i < oprsz_2; i += 1) {
3304             intptr_t il = H1(i);
3305             intptr_t ih = H1(oprsz - 1 - i);
3306             uint8_t l = reverse_bits_8(*(uint8_t *)(vn + il), esz);
3307             uint8_t h = reverse_bits_8(*(uint8_t *)(vn + ih), esz);
3308             *(uint8_t *)(vd + il) = h;
3309             *(uint8_t *)(vd + ih) = l;
3310         }
3311     }
3312 }
3313 
3314 void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
3315 {
3316     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3317     intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
3318     uint64_t *d = vd;
3319     intptr_t i;
3320 
3321     if (oprsz <= 8) {
3322         uint64_t nn = *(uint64_t *)vn;
3323         int half = 4 * oprsz;
3324 
3325         nn = extract64(nn, high * half, half);
3326         nn = expand_bits(nn, 0);
3327         d[0] = nn;
3328     } else {
3329         ARMPredicateReg tmp_n;
3330 
3331         /* We produce output faster than we consume input.
3332            Therefore we must be mindful of possible overlap.  */
3333         if ((vn - vd) < (uintptr_t)oprsz) {
3334             vn = memcpy(&tmp_n, vn, oprsz);
3335         }
3336         if (high) {
3337             high = oprsz >> 1;
3338         }
3339 
3340         if ((oprsz & 7) == 0) {
3341             uint32_t *n = vn;
3342             high >>= 2;
3343 
3344             for (i = 0; i < oprsz / 8; i++) {
3345                 uint64_t nn = n[H4(high + i)];
3346                 d[i] = expand_bits(nn, 0);
3347             }
3348         } else {
3349             uint16_t *d16 = vd;
3350             uint8_t *n = vn;
3351 
3352             for (i = 0; i < oprsz / 2; i++) {
3353                 uint16_t nn = n[H1(high + i)];
3354                 d16[H2(i)] = expand_bits(nn, 0);
3355             }
3356         }
3357     }
3358 }
3359 
3360 #define DO_ZIP(NAME, TYPE, H) \
3361 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)       \
3362 {                                                                    \
3363     intptr_t oprsz = simd_oprsz(desc);                               \
3364     intptr_t odd_ofs = simd_data(desc);                              \
3365     intptr_t i, oprsz_2 = oprsz / 2;                                 \
3366     ARMVectorReg tmp_n, tmp_m;                                       \
3367     /* We produce output faster than we consume input.               \
3368        Therefore we must be mindful of possible overlap.  */         \
3369     if (unlikely((vn - vd) < (uintptr_t)oprsz)) {                    \
3370         vn = memcpy(&tmp_n, vn, oprsz);                              \
3371     }                                                                \
3372     if (unlikely((vm - vd) < (uintptr_t)oprsz)) {                    \
3373         vm = memcpy(&tmp_m, vm, oprsz);                              \
3374     }                                                                \
3375     for (i = 0; i < oprsz_2; i += sizeof(TYPE)) {                    \
3376         *(TYPE *)(vd + H(2 * i + 0)) = *(TYPE *)(vn + odd_ofs + H(i)); \
3377         *(TYPE *)(vd + H(2 * i + sizeof(TYPE))) =                    \
3378             *(TYPE *)(vm + odd_ofs + H(i));                          \
3379     }                                                                \
3380     if (sizeof(TYPE) == 16 && unlikely(oprsz & 16)) {                \
3381         memset(vd + oprsz - 16, 0, 16);                              \
3382     }                                                                \
3383 }
3384 
3385 DO_ZIP(sve_zip_b, uint8_t, H1)
3386 DO_ZIP(sve_zip_h, uint16_t, H1_2)
3387 DO_ZIP(sve_zip_s, uint32_t, H1_4)
3388 DO_ZIP(sve_zip_d, uint64_t, H1_8)
3389 DO_ZIP(sve2_zip_q, Int128, )
3390 
3391 #define DO_UZP(NAME, TYPE, H) \
3392 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)         \
3393 {                                                                      \
3394     intptr_t oprsz = simd_oprsz(desc);                                 \
3395     intptr_t odd_ofs = simd_data(desc);                                \
3396     intptr_t i, p;                                                     \
3397     ARMVectorReg tmp_m;                                                \
3398     if (unlikely((vm - vd) < (uintptr_t)oprsz)) {                      \
3399         vm = memcpy(&tmp_m, vm, oprsz);                                \
3400     }                                                                  \
3401     i = 0, p = odd_ofs;                                                \
3402     do {                                                               \
3403         *(TYPE *)(vd + H(i)) = *(TYPE *)(vn + H(p));                   \
3404         i += sizeof(TYPE), p += 2 * sizeof(TYPE);                      \
3405     } while (p < oprsz);                                               \
3406     p -= oprsz;                                                        \
3407     do {                                                               \
3408         *(TYPE *)(vd + H(i)) = *(TYPE *)(vm + H(p));                   \
3409         i += sizeof(TYPE), p += 2 * sizeof(TYPE);                      \
3410     } while (p < oprsz);                                               \
3411     tcg_debug_assert(i == oprsz);                                      \
3412 }
3413 
3414 DO_UZP(sve_uzp_b, uint8_t, H1)
3415 DO_UZP(sve_uzp_h, uint16_t, H1_2)
3416 DO_UZP(sve_uzp_s, uint32_t, H1_4)
3417 DO_UZP(sve_uzp_d, uint64_t, H1_8)
3418 DO_UZP(sve2_uzp_q, Int128, )
3419 
3420 #define DO_TRN(NAME, TYPE, H) \
3421 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc)         \
3422 {                                                                      \
3423     intptr_t oprsz = simd_oprsz(desc);                                 \
3424     intptr_t odd_ofs = simd_data(desc);                                \
3425     intptr_t i;                                                        \
3426     for (i = 0; i < oprsz; i += 2 * sizeof(TYPE)) {                    \
3427         TYPE ae = *(TYPE *)(vn + H(i + odd_ofs));                      \
3428         TYPE be = *(TYPE *)(vm + H(i + odd_ofs));                      \
3429         *(TYPE *)(vd + H(i + 0)) = ae;                                 \
3430         *(TYPE *)(vd + H(i + sizeof(TYPE))) = be;                      \
3431     }                                                                  \
3432     if (sizeof(TYPE) == 16 && unlikely(oprsz & 16)) {                  \
3433         memset(vd + oprsz - 16, 0, 16);                                \
3434     }                                                                  \
3435 }
3436 
3437 DO_TRN(sve_trn_b, uint8_t, H1)
3438 DO_TRN(sve_trn_h, uint16_t, H1_2)
3439 DO_TRN(sve_trn_s, uint32_t, H1_4)
3440 DO_TRN(sve_trn_d, uint64_t, H1_8)
3441 DO_TRN(sve2_trn_q, Int128, )
3442 
3443 #undef DO_ZIP
3444 #undef DO_UZP
3445 #undef DO_TRN
3446 
3447 void HELPER(sve_compact_s)(void *vd, void *vn, void *vg, uint32_t desc)
3448 {
3449     intptr_t i, j, opr_sz = simd_oprsz(desc) / 4;
3450     uint32_t *d = vd, *n = vn;
3451     uint8_t *pg = vg;
3452 
3453     for (i = j = 0; i < opr_sz; i++) {
3454         if (pg[H1(i / 2)] & (i & 1 ? 0x10 : 0x01)) {
3455             d[H4(j)] = n[H4(i)];
3456             j++;
3457         }
3458     }
3459     for (; j < opr_sz; j++) {
3460         d[H4(j)] = 0;
3461     }
3462 }
3463 
3464 void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
3465 {
3466     intptr_t i, j, opr_sz = simd_oprsz(desc) / 8;
3467     uint64_t *d = vd, *n = vn;
3468     uint8_t *pg = vg;
3469 
3470     for (i = j = 0; i < opr_sz; i++) {
3471         if (pg[H1(i)] & 1) {
3472             d[j] = n[i];
3473             j++;
3474         }
3475     }
3476     for (; j < opr_sz; j++) {
3477         d[j] = 0;
3478     }
3479 }
3480 
3481 /* Similar to the ARM LastActiveElement pseudocode function, except the
3482  * result is multiplied by the element size.  This includes the not found
3483  * indication; e.g. not found for esz=3 is -8.
3484  */
3485 int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
3486 {
3487     intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
3488     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
3489 
3490     return last_active_element(vg, words, esz);
3491 }
3492 
3493 void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
3494 {
3495     intptr_t opr_sz = simd_oprsz(desc) / 8;
3496     int esz = simd_data(desc);
3497     uint64_t pg, first_g, last_g, len, mask = pred_esz_masks[esz];
3498     intptr_t i, first_i, last_i;
3499     ARMVectorReg tmp;
3500 
3501     first_i = last_i = 0;
3502     first_g = last_g = 0;
3503 
3504     /* Find the extent of the active elements within VG.  */
3505     for (i = QEMU_ALIGN_UP(opr_sz, 8) - 8; i >= 0; i -= 8) {
3506         pg = *(uint64_t *)(vg + i) & mask;
3507         if (pg) {
3508             if (last_g == 0) {
3509                 last_g = pg;
3510                 last_i = i;
3511             }
3512             first_g = pg;
3513             first_i = i;
3514         }
3515     }
3516 
3517     len = 0;
3518     if (first_g != 0) {
3519         first_i = first_i * 8 + ctz64(first_g);
3520         last_i = last_i * 8 + 63 - clz64(last_g);
3521         len = last_i - first_i + (1 << esz);
3522         if (vd == vm) {
3523             vm = memcpy(&tmp, vm, opr_sz * 8);
3524         }
3525         swap_memmove(vd, vn + first_i, len);
3526     }
3527     swap_memmove(vd + len, vm, opr_sz * 8 - len);
3528 }
3529 
3530 void HELPER(sve_sel_zpzz_b)(void *vd, void *vn, void *vm,
3531                             void *vg, uint32_t desc)
3532 {
3533     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
3534     uint64_t *d = vd, *n = vn, *m = vm;
3535     uint8_t *pg = vg;
3536 
3537     for (i = 0; i < opr_sz; i += 1) {
3538         uint64_t nn = n[i], mm = m[i];
3539         uint64_t pp = expand_pred_b(pg[H1(i)]);
3540         d[i] = (nn & pp) | (mm & ~pp);
3541     }
3542 }
3543 
3544 void HELPER(sve_sel_zpzz_h)(void *vd, void *vn, void *vm,
3545                             void *vg, uint32_t desc)
3546 {
3547     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
3548     uint64_t *d = vd, *n = vn, *m = vm;
3549     uint8_t *pg = vg;
3550 
3551     for (i = 0; i < opr_sz; i += 1) {
3552         uint64_t nn = n[i], mm = m[i];
3553         uint64_t pp = expand_pred_h(pg[H1(i)]);
3554         d[i] = (nn & pp) | (mm & ~pp);
3555     }
3556 }
3557 
3558 void HELPER(sve_sel_zpzz_s)(void *vd, void *vn, void *vm,
3559                             void *vg, uint32_t desc)
3560 {
3561     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
3562     uint64_t *d = vd, *n = vn, *m = vm;
3563     uint8_t *pg = vg;
3564 
3565     for (i = 0; i < opr_sz; i += 1) {
3566         uint64_t nn = n[i], mm = m[i];
3567         uint64_t pp = expand_pred_s(pg[H1(i)]);
3568         d[i] = (nn & pp) | (mm & ~pp);
3569     }
3570 }
3571 
3572 void HELPER(sve_sel_zpzz_d)(void *vd, void *vn, void *vm,
3573                             void *vg, uint32_t desc)
3574 {
3575     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
3576     uint64_t *d = vd, *n = vn, *m = vm;
3577     uint8_t *pg = vg;
3578 
3579     for (i = 0; i < opr_sz; i += 1) {
3580         uint64_t nn = n[i], mm = m[i];
3581         d[i] = (pg[H1(i)] & 1 ? nn : mm);
3582     }
3583 }
3584 
3585 void HELPER(sve_sel_zpzz_q)(void *vd, void *vn, void *vm,
3586                             void *vg, uint32_t desc)
3587 {
3588     intptr_t i, opr_sz = simd_oprsz(desc) / 16;
3589     Int128 *d = vd, *n = vn, *m = vm;
3590     uint16_t *pg = vg;
3591 
3592     for (i = 0; i < opr_sz; i += 1) {
3593         d[i] = (pg[H2(i)] & 1 ? n : m)[i];
3594     }
3595 }
3596 
3597 /* Two operand comparison controlled by a predicate.
3598  * ??? It is very tempting to want to be able to expand this inline
3599  * with x86 instructions, e.g.
3600  *
3601  *    vcmpeqw    zm, zn, %ymm0
3602  *    vpmovmskb  %ymm0, %eax
3603  *    and        $0x5555, %eax
3604  *    and        pg, %eax
3605  *
3606  * or even aarch64, e.g.
3607  *
3608  *    // mask = 4000 1000 0400 0100 0040 0010 0004 0001
3609  *    cmeq       v0.8h, zn, zm
3610  *    and        v0.8h, v0.8h, mask
3611  *    addv       h0, v0.8h
3612  *    and        v0.8b, pg
3613  *
3614  * However, coming up with an abstraction that allows vector inputs and
3615  * a scalar output, and also handles the byte-ordering of sub-uint64_t
3616  * scalar outputs, is tricky.
3617  */
3618 #define DO_CMP_PPZZ(NAME, TYPE, OP, H, MASK)                                 \
3619 uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
3620 {                                                                            \
3621     intptr_t opr_sz = simd_oprsz(desc);                                      \
3622     uint32_t flags = PREDTEST_INIT;                                          \
3623     intptr_t i = opr_sz;                                                     \
3624     do {                                                                     \
3625         uint64_t out = 0, pg;                                                \
3626         do {                                                                 \
3627             i -= sizeof(TYPE), out <<= sizeof(TYPE);                         \
3628             TYPE nn = *(TYPE *)(vn + H(i));                                  \
3629             TYPE mm = *(TYPE *)(vm + H(i));                                  \
3630             out |= nn OP mm;                                                 \
3631         } while (i & 63);                                                    \
3632         pg = *(uint64_t *)(vg + (i >> 3)) & MASK;                            \
3633         out &= pg;                                                           \
3634         *(uint64_t *)(vd + (i >> 3)) = out;                                  \
3635         flags = iter_predtest_bwd(out, pg, flags);                           \
3636     } while (i > 0);                                                         \
3637     return flags;                                                            \
3638 }
3639 
3640 #define DO_CMP_PPZZ_B(NAME, TYPE, OP) \
3641     DO_CMP_PPZZ(NAME, TYPE, OP, H1,   0xffffffffffffffffull)
3642 #define DO_CMP_PPZZ_H(NAME, TYPE, OP) \
3643     DO_CMP_PPZZ(NAME, TYPE, OP, H1_2, 0x5555555555555555ull)
3644 #define DO_CMP_PPZZ_S(NAME, TYPE, OP) \
3645     DO_CMP_PPZZ(NAME, TYPE, OP, H1_4, 0x1111111111111111ull)
3646 #define DO_CMP_PPZZ_D(NAME, TYPE, OP) \
3647     DO_CMP_PPZZ(NAME, TYPE, OP, H1_8, 0x0101010101010101ull)
3648 
3649 DO_CMP_PPZZ_B(sve_cmpeq_ppzz_b, uint8_t,  ==)
3650 DO_CMP_PPZZ_H(sve_cmpeq_ppzz_h, uint16_t, ==)
3651 DO_CMP_PPZZ_S(sve_cmpeq_ppzz_s, uint32_t, ==)
3652 DO_CMP_PPZZ_D(sve_cmpeq_ppzz_d, uint64_t, ==)
3653 
3654 DO_CMP_PPZZ_B(sve_cmpne_ppzz_b, uint8_t,  !=)
3655 DO_CMP_PPZZ_H(sve_cmpne_ppzz_h, uint16_t, !=)
3656 DO_CMP_PPZZ_S(sve_cmpne_ppzz_s, uint32_t, !=)
3657 DO_CMP_PPZZ_D(sve_cmpne_ppzz_d, uint64_t, !=)
3658 
3659 DO_CMP_PPZZ_B(sve_cmpgt_ppzz_b, int8_t,  >)
3660 DO_CMP_PPZZ_H(sve_cmpgt_ppzz_h, int16_t, >)
3661 DO_CMP_PPZZ_S(sve_cmpgt_ppzz_s, int32_t, >)
3662 DO_CMP_PPZZ_D(sve_cmpgt_ppzz_d, int64_t, >)
3663 
3664 DO_CMP_PPZZ_B(sve_cmpge_ppzz_b, int8_t,  >=)
3665 DO_CMP_PPZZ_H(sve_cmpge_ppzz_h, int16_t, >=)
3666 DO_CMP_PPZZ_S(sve_cmpge_ppzz_s, int32_t, >=)
3667 DO_CMP_PPZZ_D(sve_cmpge_ppzz_d, int64_t, >=)
3668 
3669 DO_CMP_PPZZ_B(sve_cmphi_ppzz_b, uint8_t,  >)
3670 DO_CMP_PPZZ_H(sve_cmphi_ppzz_h, uint16_t, >)
3671 DO_CMP_PPZZ_S(sve_cmphi_ppzz_s, uint32_t, >)
3672 DO_CMP_PPZZ_D(sve_cmphi_ppzz_d, uint64_t, >)
3673 
3674 DO_CMP_PPZZ_B(sve_cmphs_ppzz_b, uint8_t,  >=)
3675 DO_CMP_PPZZ_H(sve_cmphs_ppzz_h, uint16_t, >=)
3676 DO_CMP_PPZZ_S(sve_cmphs_ppzz_s, uint32_t, >=)
3677 DO_CMP_PPZZ_D(sve_cmphs_ppzz_d, uint64_t, >=)
3678 
3679 #undef DO_CMP_PPZZ_B
3680 #undef DO_CMP_PPZZ_H
3681 #undef DO_CMP_PPZZ_S
3682 #undef DO_CMP_PPZZ_D
3683 #undef DO_CMP_PPZZ
3684 
3685 /* Similar, but the second source is "wide".  */
3686 #define DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H, MASK)                     \
3687 uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \
3688 {                                                                            \
3689     intptr_t opr_sz = simd_oprsz(desc);                                      \
3690     uint32_t flags = PREDTEST_INIT;                                          \
3691     intptr_t i = opr_sz;                                                     \
3692     do {                                                                     \
3693         uint64_t out = 0, pg;                                                \
3694         do {                                                                 \
3695             TYPEW mm = *(TYPEW *)(vm + i - 8);                               \
3696             do {                                                             \
3697                 i -= sizeof(TYPE), out <<= sizeof(TYPE);                     \
3698                 TYPE nn = *(TYPE *)(vn + H(i));                              \
3699                 out |= nn OP mm;                                             \
3700             } while (i & 7);                                                 \
3701         } while (i & 63);                                                    \
3702         pg = *(uint64_t *)(vg + (i >> 3)) & MASK;                            \
3703         out &= pg;                                                           \
3704         *(uint64_t *)(vd + (i >> 3)) = out;                                  \
3705         flags = iter_predtest_bwd(out, pg, flags);                           \
3706     } while (i > 0);                                                         \
3707     return flags;                                                            \
3708 }
3709 
3710 #define DO_CMP_PPZW_B(NAME, TYPE, TYPEW, OP) \
3711     DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1,   0xffffffffffffffffull)
3712 #define DO_CMP_PPZW_H(NAME, TYPE, TYPEW, OP) \
3713     DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1_2, 0x5555555555555555ull)
3714 #define DO_CMP_PPZW_S(NAME, TYPE, TYPEW, OP) \
3715     DO_CMP_PPZW(NAME, TYPE, TYPEW, OP, H1_4, 0x1111111111111111ull)
3716 
3717 DO_CMP_PPZW_B(sve_cmpeq_ppzw_b, int8_t,  uint64_t, ==)
3718 DO_CMP_PPZW_H(sve_cmpeq_ppzw_h, int16_t, uint64_t, ==)
3719 DO_CMP_PPZW_S(sve_cmpeq_ppzw_s, int32_t, uint64_t, ==)
3720 
3721 DO_CMP_PPZW_B(sve_cmpne_ppzw_b, int8_t,  uint64_t, !=)
3722 DO_CMP_PPZW_H(sve_cmpne_ppzw_h, int16_t, uint64_t, !=)
3723 DO_CMP_PPZW_S(sve_cmpne_ppzw_s, int32_t, uint64_t, !=)
3724 
3725 DO_CMP_PPZW_B(sve_cmpgt_ppzw_b, int8_t,   int64_t, >)
3726 DO_CMP_PPZW_H(sve_cmpgt_ppzw_h, int16_t,  int64_t, >)
3727 DO_CMP_PPZW_S(sve_cmpgt_ppzw_s, int32_t,  int64_t, >)
3728 
3729 DO_CMP_PPZW_B(sve_cmpge_ppzw_b, int8_t,   int64_t, >=)
3730 DO_CMP_PPZW_H(sve_cmpge_ppzw_h, int16_t,  int64_t, >=)
3731 DO_CMP_PPZW_S(sve_cmpge_ppzw_s, int32_t,  int64_t, >=)
3732 
3733 DO_CMP_PPZW_B(sve_cmphi_ppzw_b, uint8_t,  uint64_t, >)
3734 DO_CMP_PPZW_H(sve_cmphi_ppzw_h, uint16_t, uint64_t, >)
3735 DO_CMP_PPZW_S(sve_cmphi_ppzw_s, uint32_t, uint64_t, >)
3736 
3737 DO_CMP_PPZW_B(sve_cmphs_ppzw_b, uint8_t,  uint64_t, >=)
3738 DO_CMP_PPZW_H(sve_cmphs_ppzw_h, uint16_t, uint64_t, >=)
3739 DO_CMP_PPZW_S(sve_cmphs_ppzw_s, uint32_t, uint64_t, >=)
3740 
3741 DO_CMP_PPZW_B(sve_cmplt_ppzw_b, int8_t,   int64_t, <)
3742 DO_CMP_PPZW_H(sve_cmplt_ppzw_h, int16_t,  int64_t, <)
3743 DO_CMP_PPZW_S(sve_cmplt_ppzw_s, int32_t,  int64_t, <)
3744 
3745 DO_CMP_PPZW_B(sve_cmple_ppzw_b, int8_t,   int64_t, <=)
3746 DO_CMP_PPZW_H(sve_cmple_ppzw_h, int16_t,  int64_t, <=)
3747 DO_CMP_PPZW_S(sve_cmple_ppzw_s, int32_t,  int64_t, <=)
3748 
3749 DO_CMP_PPZW_B(sve_cmplo_ppzw_b, uint8_t,  uint64_t, <)
3750 DO_CMP_PPZW_H(sve_cmplo_ppzw_h, uint16_t, uint64_t, <)
3751 DO_CMP_PPZW_S(sve_cmplo_ppzw_s, uint32_t, uint64_t, <)
3752 
3753 DO_CMP_PPZW_B(sve_cmpls_ppzw_b, uint8_t,  uint64_t, <=)
3754 DO_CMP_PPZW_H(sve_cmpls_ppzw_h, uint16_t, uint64_t, <=)
3755 DO_CMP_PPZW_S(sve_cmpls_ppzw_s, uint32_t, uint64_t, <=)
3756 
3757 #undef DO_CMP_PPZW_B
3758 #undef DO_CMP_PPZW_H
3759 #undef DO_CMP_PPZW_S
3760 #undef DO_CMP_PPZW
3761 
3762 /* Similar, but the second source is immediate.  */
3763 #define DO_CMP_PPZI(NAME, TYPE, OP, H, MASK)                         \
3764 uint32_t HELPER(NAME)(void *vd, void *vn, void *vg, uint32_t desc)   \
3765 {                                                                    \
3766     intptr_t opr_sz = simd_oprsz(desc);                              \
3767     uint32_t flags = PREDTEST_INIT;                                  \
3768     TYPE mm = simd_data(desc);                                       \
3769     intptr_t i = opr_sz;                                             \
3770     do {                                                             \
3771         uint64_t out = 0, pg;                                        \
3772         do {                                                         \
3773             i -= sizeof(TYPE), out <<= sizeof(TYPE);                 \
3774             TYPE nn = *(TYPE *)(vn + H(i));                          \
3775             out |= nn OP mm;                                         \
3776         } while (i & 63);                                            \
3777         pg = *(uint64_t *)(vg + (i >> 3)) & MASK;                    \
3778         out &= pg;                                                   \
3779         *(uint64_t *)(vd + (i >> 3)) = out;                          \
3780         flags = iter_predtest_bwd(out, pg, flags);                   \
3781     } while (i > 0);                                                 \
3782     return flags;                                                    \
3783 }
3784 
3785 #define DO_CMP_PPZI_B(NAME, TYPE, OP) \
3786     DO_CMP_PPZI(NAME, TYPE, OP, H1,   0xffffffffffffffffull)
3787 #define DO_CMP_PPZI_H(NAME, TYPE, OP) \
3788     DO_CMP_PPZI(NAME, TYPE, OP, H1_2, 0x5555555555555555ull)
3789 #define DO_CMP_PPZI_S(NAME, TYPE, OP) \
3790     DO_CMP_PPZI(NAME, TYPE, OP, H1_4, 0x1111111111111111ull)
3791 #define DO_CMP_PPZI_D(NAME, TYPE, OP) \
3792     DO_CMP_PPZI(NAME, TYPE, OP, H1_8, 0x0101010101010101ull)
3793 
3794 DO_CMP_PPZI_B(sve_cmpeq_ppzi_b, uint8_t,  ==)
3795 DO_CMP_PPZI_H(sve_cmpeq_ppzi_h, uint16_t, ==)
3796 DO_CMP_PPZI_S(sve_cmpeq_ppzi_s, uint32_t, ==)
3797 DO_CMP_PPZI_D(sve_cmpeq_ppzi_d, uint64_t, ==)
3798 
3799 DO_CMP_PPZI_B(sve_cmpne_ppzi_b, uint8_t,  !=)
3800 DO_CMP_PPZI_H(sve_cmpne_ppzi_h, uint16_t, !=)
3801 DO_CMP_PPZI_S(sve_cmpne_ppzi_s, uint32_t, !=)
3802 DO_CMP_PPZI_D(sve_cmpne_ppzi_d, uint64_t, !=)
3803 
3804 DO_CMP_PPZI_B(sve_cmpgt_ppzi_b, int8_t,  >)
3805 DO_CMP_PPZI_H(sve_cmpgt_ppzi_h, int16_t, >)
3806 DO_CMP_PPZI_S(sve_cmpgt_ppzi_s, int32_t, >)
3807 DO_CMP_PPZI_D(sve_cmpgt_ppzi_d, int64_t, >)
3808 
3809 DO_CMP_PPZI_B(sve_cmpge_ppzi_b, int8_t,  >=)
3810 DO_CMP_PPZI_H(sve_cmpge_ppzi_h, int16_t, >=)
3811 DO_CMP_PPZI_S(sve_cmpge_ppzi_s, int32_t, >=)
3812 DO_CMP_PPZI_D(sve_cmpge_ppzi_d, int64_t, >=)
3813 
3814 DO_CMP_PPZI_B(sve_cmphi_ppzi_b, uint8_t,  >)
3815 DO_CMP_PPZI_H(sve_cmphi_ppzi_h, uint16_t, >)
3816 DO_CMP_PPZI_S(sve_cmphi_ppzi_s, uint32_t, >)
3817 DO_CMP_PPZI_D(sve_cmphi_ppzi_d, uint64_t, >)
3818 
3819 DO_CMP_PPZI_B(sve_cmphs_ppzi_b, uint8_t,  >=)
3820 DO_CMP_PPZI_H(sve_cmphs_ppzi_h, uint16_t, >=)
3821 DO_CMP_PPZI_S(sve_cmphs_ppzi_s, uint32_t, >=)
3822 DO_CMP_PPZI_D(sve_cmphs_ppzi_d, uint64_t, >=)
3823 
3824 DO_CMP_PPZI_B(sve_cmplt_ppzi_b, int8_t,  <)
3825 DO_CMP_PPZI_H(sve_cmplt_ppzi_h, int16_t, <)
3826 DO_CMP_PPZI_S(sve_cmplt_ppzi_s, int32_t, <)
3827 DO_CMP_PPZI_D(sve_cmplt_ppzi_d, int64_t, <)
3828 
3829 DO_CMP_PPZI_B(sve_cmple_ppzi_b, int8_t,  <=)
3830 DO_CMP_PPZI_H(sve_cmple_ppzi_h, int16_t, <=)
3831 DO_CMP_PPZI_S(sve_cmple_ppzi_s, int32_t, <=)
3832 DO_CMP_PPZI_D(sve_cmple_ppzi_d, int64_t, <=)
3833 
3834 DO_CMP_PPZI_B(sve_cmplo_ppzi_b, uint8_t,  <)
3835 DO_CMP_PPZI_H(sve_cmplo_ppzi_h, uint16_t, <)
3836 DO_CMP_PPZI_S(sve_cmplo_ppzi_s, uint32_t, <)
3837 DO_CMP_PPZI_D(sve_cmplo_ppzi_d, uint64_t, <)
3838 
3839 DO_CMP_PPZI_B(sve_cmpls_ppzi_b, uint8_t,  <=)
3840 DO_CMP_PPZI_H(sve_cmpls_ppzi_h, uint16_t, <=)
3841 DO_CMP_PPZI_S(sve_cmpls_ppzi_s, uint32_t, <=)
3842 DO_CMP_PPZI_D(sve_cmpls_ppzi_d, uint64_t, <=)
3843 
3844 #undef DO_CMP_PPZI_B
3845 #undef DO_CMP_PPZI_H
3846 #undef DO_CMP_PPZI_S
3847 #undef DO_CMP_PPZI_D
3848 #undef DO_CMP_PPZI
3849 
3850 /* Similar to the ARM LastActive pseudocode function.  */
3851 static bool last_active_pred(void *vd, void *vg, intptr_t oprsz)
3852 {
3853     intptr_t i;
3854 
3855     for (i = QEMU_ALIGN_UP(oprsz, 8) - 8; i >= 0; i -= 8) {
3856         uint64_t pg = *(uint64_t *)(vg + i);
3857         if (pg) {
3858             return (pow2floor(pg) & *(uint64_t *)(vd + i)) != 0;
3859         }
3860     }
3861     return 0;
3862 }
3863 
3864 /* Compute a mask into RETB that is true for all G, up to and including
3865  * (if after) or excluding (if !after) the first G & N.
3866  * Return true if BRK found.
3867  */
3868 static bool compute_brk(uint64_t *retb, uint64_t n, uint64_t g,
3869                         bool brk, bool after)
3870 {
3871     uint64_t b;
3872 
3873     if (brk) {
3874         b = 0;
3875     } else if ((g & n) == 0) {
3876         /* For all G, no N are set; break not found.  */
3877         b = g;
3878     } else {
3879         /* Break somewhere in N.  Locate it.  */
3880         b = g & n;            /* guard true, pred true */
3881         b = b & -b;           /* first such */
3882         if (after) {
3883             b = b | (b - 1);  /* break after same */
3884         } else {
3885             b = b - 1;        /* break before same */
3886         }
3887         brk = true;
3888     }
3889 
3890     *retb = b;
3891     return brk;
3892 }
3893 
3894 /* Compute a zeroing BRK.  */
3895 static void compute_brk_z(uint64_t *d, uint64_t *n, uint64_t *g,
3896                           intptr_t oprsz, bool after)
3897 {
3898     bool brk = false;
3899     intptr_t i;
3900 
3901     for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
3902         uint64_t this_b, this_g = g[i];
3903 
3904         brk = compute_brk(&this_b, n[i], this_g, brk, after);
3905         d[i] = this_b & this_g;
3906     }
3907 }
3908 
3909 /* Likewise, but also compute flags.  */
3910 static uint32_t compute_brks_z(uint64_t *d, uint64_t *n, uint64_t *g,
3911                                intptr_t oprsz, bool after)
3912 {
3913     uint32_t flags = PREDTEST_INIT;
3914     bool brk = false;
3915     intptr_t i;
3916 
3917     for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
3918         uint64_t this_b, this_d, this_g = g[i];
3919 
3920         brk = compute_brk(&this_b, n[i], this_g, brk, after);
3921         d[i] = this_d = this_b & this_g;
3922         flags = iter_predtest_fwd(this_d, this_g, flags);
3923     }
3924     return flags;
3925 }
3926 
3927 /* Compute a merging BRK.  */
3928 static void compute_brk_m(uint64_t *d, uint64_t *n, uint64_t *g,
3929                           intptr_t oprsz, bool after)
3930 {
3931     bool brk = false;
3932     intptr_t i;
3933 
3934     for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
3935         uint64_t this_b, this_g = g[i];
3936 
3937         brk = compute_brk(&this_b, n[i], this_g, brk, after);
3938         d[i] = (this_b & this_g) | (d[i] & ~this_g);
3939     }
3940 }
3941 
3942 /* Likewise, but also compute flags.  */
3943 static uint32_t compute_brks_m(uint64_t *d, uint64_t *n, uint64_t *g,
3944                                intptr_t oprsz, bool after)
3945 {
3946     uint32_t flags = PREDTEST_INIT;
3947     bool brk = false;
3948     intptr_t i;
3949 
3950     for (i = 0; i < oprsz / 8; ++i) {
3951         uint64_t this_b, this_d = d[i], this_g = g[i];
3952 
3953         brk = compute_brk(&this_b, n[i], this_g, brk, after);
3954         d[i] = this_d = (this_b & this_g) | (this_d & ~this_g);
3955         flags = iter_predtest_fwd(this_d, this_g, flags);
3956     }
3957     return flags;
3958 }
3959 
3960 static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
3961 {
3962     /* It is quicker to zero the whole predicate than loop on OPRSZ.
3963      * The compiler should turn this into 4 64-bit integer stores.
3964      */
3965     memset(d, 0, sizeof(ARMPredicateReg));
3966     return PREDTEST_INIT;
3967 }
3968 
3969 void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
3970                        uint32_t pred_desc)
3971 {
3972     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3973     if (last_active_pred(vn, vg, oprsz)) {
3974         compute_brk_z(vd, vm, vg, oprsz, true);
3975     } else {
3976         do_zero(vd, oprsz);
3977     }
3978 }
3979 
3980 uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
3981                             uint32_t pred_desc)
3982 {
3983     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3984     if (last_active_pred(vn, vg, oprsz)) {
3985         return compute_brks_z(vd, vm, vg, oprsz, true);
3986     } else {
3987         return do_zero(vd, oprsz);
3988     }
3989 }
3990 
3991 void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
3992                        uint32_t pred_desc)
3993 {
3994     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
3995     if (last_active_pred(vn, vg, oprsz)) {
3996         compute_brk_z(vd, vm, vg, oprsz, false);
3997     } else {
3998         do_zero(vd, oprsz);
3999     }
4000 }
4001 
4002 uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
4003                             uint32_t pred_desc)
4004 {
4005     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4006     if (last_active_pred(vn, vg, oprsz)) {
4007         return compute_brks_z(vd, vm, vg, oprsz, false);
4008     } else {
4009         return do_zero(vd, oprsz);
4010     }
4011 }
4012 
4013 void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4014 {
4015     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4016     compute_brk_z(vd, vn, vg, oprsz, true);
4017 }
4018 
4019 uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4020 {
4021     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4022     return compute_brks_z(vd, vn, vg, oprsz, true);
4023 }
4024 
4025 void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4026 {
4027     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4028     compute_brk_z(vd, vn, vg, oprsz, false);
4029 }
4030 
4031 uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4032 {
4033     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4034     return compute_brks_z(vd, vn, vg, oprsz, false);
4035 }
4036 
4037 void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4038 {
4039     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4040     compute_brk_m(vd, vn, vg, oprsz, true);
4041 }
4042 
4043 uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4044 {
4045     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4046     return compute_brks_m(vd, vn, vg, oprsz, true);
4047 }
4048 
4049 void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4050 {
4051     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4052     compute_brk_m(vd, vn, vg, oprsz, false);
4053 }
4054 
4055 uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4056 {
4057     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4058     return compute_brks_m(vd, vn, vg, oprsz, false);
4059 }
4060 
4061 void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4062 {
4063     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4064     if (!last_active_pred(vn, vg, oprsz)) {
4065         do_zero(vd, oprsz);
4066     }
4067 }
4068 
4069 /* As if PredTest(Ones(PL), D, esz).  */
4070 static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
4071                               uint64_t esz_mask)
4072 {
4073     uint32_t flags = PREDTEST_INIT;
4074     intptr_t i;
4075 
4076     for (i = 0; i < oprsz / 8; i++) {
4077         flags = iter_predtest_fwd(d->p[i], esz_mask, flags);
4078     }
4079     if (oprsz & 7) {
4080         uint64_t mask = ~(-1ULL << (8 * (oprsz & 7)));
4081         flags = iter_predtest_fwd(d->p[i], esz_mask & mask, flags);
4082     }
4083     return flags;
4084 }
4085 
4086 uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
4087 {
4088     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4089     if (last_active_pred(vn, vg, oprsz)) {
4090         return predtest_ones(vd, oprsz, -1);
4091     } else {
4092         return do_zero(vd, oprsz);
4093     }
4094 }
4095 
4096 uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
4097 {
4098     intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
4099     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
4100     uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
4101     intptr_t i;
4102 
4103     for (i = 0; i < words; ++i) {
4104         uint64_t t = n[i] & g[i] & mask;
4105         sum += ctpop64(t);
4106     }
4107     return sum;
4108 }
4109 
4110 uint32_t HELPER(sve_whilel)(void *vd, uint32_t count, uint32_t pred_desc)
4111 {
4112     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4113     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
4114     uint64_t esz_mask = pred_esz_masks[esz];
4115     ARMPredicateReg *d = vd;
4116     uint32_t flags;
4117     intptr_t i;
4118 
4119     /* Begin with a zero predicate register.  */
4120     flags = do_zero(d, oprsz);
4121     if (count == 0) {
4122         return flags;
4123     }
4124 
4125     /* Set all of the requested bits.  */
4126     for (i = 0; i < count / 64; ++i) {
4127         d->p[i] = esz_mask;
4128     }
4129     if (count & 63) {
4130         d->p[i] = MAKE_64BIT_MASK(0, count & 63) & esz_mask;
4131     }
4132 
4133     return predtest_ones(d, oprsz, esz_mask);
4134 }
4135 
4136 uint32_t HELPER(sve_whileg)(void *vd, uint32_t count, uint32_t pred_desc)
4137 {
4138     intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
4139     intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
4140     uint64_t esz_mask = pred_esz_masks[esz];
4141     ARMPredicateReg *d = vd;
4142     intptr_t i, invcount, oprbits;
4143     uint64_t bits;
4144 
4145     if (count == 0) {
4146         return do_zero(d, oprsz);
4147     }
4148 
4149     oprbits = oprsz * 8;
4150     tcg_debug_assert(count <= oprbits);
4151 
4152     bits = esz_mask;
4153     if (oprbits & 63) {
4154         bits &= MAKE_64BIT_MASK(0, oprbits & 63);
4155     }
4156 
4157     invcount = oprbits - count;
4158     for (i = (oprsz - 1) / 8; i > invcount / 64; --i) {
4159         d->p[i] = bits;
4160         bits = esz_mask;
4161     }
4162 
4163     d->p[i] = bits & MAKE_64BIT_MASK(invcount & 63, 64);
4164 
4165     while (--i >= 0) {
4166         d->p[i] = 0;
4167     }
4168 
4169     return predtest_ones(d, oprsz, esz_mask);
4170 }
4171 
4172 /* Recursive reduction on a function;
4173  * C.f. the ARM ARM function ReducePredicated.
4174  *
4175  * While it would be possible to write this without the DATA temporary,
4176  * it is much simpler to process the predicate register this way.
4177  * The recursion is bounded to depth 7 (128 fp16 elements), so there's
4178  * little to gain with a more complex non-recursive form.
4179  */
4180 #define DO_REDUCE(NAME, TYPE, H, FUNC, IDENT)                         \
4181 static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
4182 {                                                                     \
4183     if (n == 1) {                                                     \
4184         return *data;                                                 \
4185     } else {                                                          \
4186         uintptr_t half = n / 2;                                       \
4187         TYPE lo = NAME##_reduce(data, status, half);                  \
4188         TYPE hi = NAME##_reduce(data + half, status, half);           \
4189         return TYPE##_##FUNC(lo, hi, status);                         \
4190     }                                                                 \
4191 }                                                                     \
4192 uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc)    \
4193 {                                                                     \
4194     uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc);   \
4195     TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)];                   \
4196     for (i = 0; i < oprsz; ) {                                        \
4197         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));               \
4198         do {                                                          \
4199             TYPE nn = *(TYPE *)(vn + H(i));                           \
4200             *(TYPE *)((void *)data + i) = (pg & 1 ? nn : IDENT);      \
4201             i += sizeof(TYPE), pg >>= sizeof(TYPE);                   \
4202         } while (i & 15);                                             \
4203     }                                                                 \
4204     for (; i < maxsz; i += sizeof(TYPE)) {                            \
4205         *(TYPE *)((void *)data + i) = IDENT;                          \
4206     }                                                                 \
4207     return NAME##_reduce(data, vs, maxsz / sizeof(TYPE));             \
4208 }
4209 
4210 DO_REDUCE(sve_faddv_h, float16, H1_2, add, float16_zero)
4211 DO_REDUCE(sve_faddv_s, float32, H1_4, add, float32_zero)
4212 DO_REDUCE(sve_faddv_d, float64, H1_8, add, float64_zero)
4213 
4214 /* Identity is floatN_default_nan, without the function call.  */
4215 DO_REDUCE(sve_fminnmv_h, float16, H1_2, minnum, 0x7E00)
4216 DO_REDUCE(sve_fminnmv_s, float32, H1_4, minnum, 0x7FC00000)
4217 DO_REDUCE(sve_fminnmv_d, float64, H1_8, minnum, 0x7FF8000000000000ULL)
4218 
4219 DO_REDUCE(sve_fmaxnmv_h, float16, H1_2, maxnum, 0x7E00)
4220 DO_REDUCE(sve_fmaxnmv_s, float32, H1_4, maxnum, 0x7FC00000)
4221 DO_REDUCE(sve_fmaxnmv_d, float64, H1_8, maxnum, 0x7FF8000000000000ULL)
4222 
4223 DO_REDUCE(sve_fminv_h, float16, H1_2, min, float16_infinity)
4224 DO_REDUCE(sve_fminv_s, float32, H1_4, min, float32_infinity)
4225 DO_REDUCE(sve_fminv_d, float64, H1_8, min, float64_infinity)
4226 
4227 DO_REDUCE(sve_fmaxv_h, float16, H1_2, max, float16_chs(float16_infinity))
4228 DO_REDUCE(sve_fmaxv_s, float32, H1_4, max, float32_chs(float32_infinity))
4229 DO_REDUCE(sve_fmaxv_d, float64, H1_8, max, float64_chs(float64_infinity))
4230 
4231 #undef DO_REDUCE
4232 
4233 uint64_t HELPER(sve_fadda_h)(uint64_t nn, void *vm, void *vg,
4234                              void *status, uint32_t desc)
4235 {
4236     intptr_t i = 0, opr_sz = simd_oprsz(desc);
4237     float16 result = nn;
4238 
4239     do {
4240         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
4241         do {
4242             if (pg & 1) {
4243                 float16 mm = *(float16 *)(vm + H1_2(i));
4244                 result = float16_add(result, mm, status);
4245             }
4246             i += sizeof(float16), pg >>= sizeof(float16);
4247         } while (i & 15);
4248     } while (i < opr_sz);
4249 
4250     return result;
4251 }
4252 
4253 uint64_t HELPER(sve_fadda_s)(uint64_t nn, void *vm, void *vg,
4254                              void *status, uint32_t desc)
4255 {
4256     intptr_t i = 0, opr_sz = simd_oprsz(desc);
4257     float32 result = nn;
4258 
4259     do {
4260         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3));
4261         do {
4262             if (pg & 1) {
4263                 float32 mm = *(float32 *)(vm + H1_2(i));
4264                 result = float32_add(result, mm, status);
4265             }
4266             i += sizeof(float32), pg >>= sizeof(float32);
4267         } while (i & 15);
4268     } while (i < opr_sz);
4269 
4270     return result;
4271 }
4272 
4273 uint64_t HELPER(sve_fadda_d)(uint64_t nn, void *vm, void *vg,
4274                              void *status, uint32_t desc)
4275 {
4276     intptr_t i = 0, opr_sz = simd_oprsz(desc) / 8;
4277     uint64_t *m = vm;
4278     uint8_t *pg = vg;
4279 
4280     for (i = 0; i < opr_sz; i++) {
4281         if (pg[H1(i)] & 1) {
4282             nn = float64_add(nn, m[i], status);
4283         }
4284     }
4285 
4286     return nn;
4287 }
4288 
4289 /* Fully general three-operand expander, controlled by a predicate,
4290  * With the extra float_status parameter.
4291  */
4292 #define DO_ZPZZ_FP(NAME, TYPE, H, OP)                           \
4293 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg,       \
4294                   void *status, uint32_t desc)                  \
4295 {                                                               \
4296     intptr_t i = simd_oprsz(desc);                              \
4297     uint64_t *g = vg;                                           \
4298     do {                                                        \
4299         uint64_t pg = g[(i - 1) >> 6];                          \
4300         do {                                                    \
4301             i -= sizeof(TYPE);                                  \
4302             if (likely((pg >> (i & 63)) & 1)) {                 \
4303                 TYPE nn = *(TYPE *)(vn + H(i));                 \
4304                 TYPE mm = *(TYPE *)(vm + H(i));                 \
4305                 *(TYPE *)(vd + H(i)) = OP(nn, mm, status);      \
4306             }                                                   \
4307         } while (i & 63);                                       \
4308     } while (i != 0);                                           \
4309 }
4310 
4311 DO_ZPZZ_FP(sve_fadd_h, uint16_t, H1_2, float16_add)
4312 DO_ZPZZ_FP(sve_fadd_s, uint32_t, H1_4, float32_add)
4313 DO_ZPZZ_FP(sve_fadd_d, uint64_t, H1_8, float64_add)
4314 
4315 DO_ZPZZ_FP(sve_fsub_h, uint16_t, H1_2, float16_sub)
4316 DO_ZPZZ_FP(sve_fsub_s, uint32_t, H1_4, float32_sub)
4317 DO_ZPZZ_FP(sve_fsub_d, uint64_t, H1_8, float64_sub)
4318 
4319 DO_ZPZZ_FP(sve_fmul_h, uint16_t, H1_2, float16_mul)
4320 DO_ZPZZ_FP(sve_fmul_s, uint32_t, H1_4, float32_mul)
4321 DO_ZPZZ_FP(sve_fmul_d, uint64_t, H1_8, float64_mul)
4322 
4323 DO_ZPZZ_FP(sve_fdiv_h, uint16_t, H1_2, float16_div)
4324 DO_ZPZZ_FP(sve_fdiv_s, uint32_t, H1_4, float32_div)
4325 DO_ZPZZ_FP(sve_fdiv_d, uint64_t, H1_8, float64_div)
4326 
4327 DO_ZPZZ_FP(sve_fmin_h, uint16_t, H1_2, float16_min)
4328 DO_ZPZZ_FP(sve_fmin_s, uint32_t, H1_4, float32_min)
4329 DO_ZPZZ_FP(sve_fmin_d, uint64_t, H1_8, float64_min)
4330 
4331 DO_ZPZZ_FP(sve_fmax_h, uint16_t, H1_2, float16_max)
4332 DO_ZPZZ_FP(sve_fmax_s, uint32_t, H1_4, float32_max)
4333 DO_ZPZZ_FP(sve_fmax_d, uint64_t, H1_8, float64_max)
4334 
4335 DO_ZPZZ_FP(sve_fminnum_h, uint16_t, H1_2, float16_minnum)
4336 DO_ZPZZ_FP(sve_fminnum_s, uint32_t, H1_4, float32_minnum)
4337 DO_ZPZZ_FP(sve_fminnum_d, uint64_t, H1_8, float64_minnum)
4338 
4339 DO_ZPZZ_FP(sve_fmaxnum_h, uint16_t, H1_2, float16_maxnum)
4340 DO_ZPZZ_FP(sve_fmaxnum_s, uint32_t, H1_4, float32_maxnum)
4341 DO_ZPZZ_FP(sve_fmaxnum_d, uint64_t, H1_8, float64_maxnum)
4342 
4343 static inline float16 abd_h(float16 a, float16 b, float_status *s)
4344 {
4345     return float16_abs(float16_sub(a, b, s));
4346 }
4347 
4348 static inline float32 abd_s(float32 a, float32 b, float_status *s)
4349 {
4350     return float32_abs(float32_sub(a, b, s));
4351 }
4352 
4353 static inline float64 abd_d(float64 a, float64 b, float_status *s)
4354 {
4355     return float64_abs(float64_sub(a, b, s));
4356 }
4357 
4358 DO_ZPZZ_FP(sve_fabd_h, uint16_t, H1_2, abd_h)
4359 DO_ZPZZ_FP(sve_fabd_s, uint32_t, H1_4, abd_s)
4360 DO_ZPZZ_FP(sve_fabd_d, uint64_t, H1_8, abd_d)
4361 
4362 static inline float64 scalbn_d(float64 a, int64_t b, float_status *s)
4363 {
4364     int b_int = MIN(MAX(b, INT_MIN), INT_MAX);
4365     return float64_scalbn(a, b_int, s);
4366 }
4367 
4368 DO_ZPZZ_FP(sve_fscalbn_h, int16_t, H1_2, float16_scalbn)
4369 DO_ZPZZ_FP(sve_fscalbn_s, int32_t, H1_4, float32_scalbn)
4370 DO_ZPZZ_FP(sve_fscalbn_d, int64_t, H1_8, scalbn_d)
4371 
4372 DO_ZPZZ_FP(sve_fmulx_h, uint16_t, H1_2, helper_advsimd_mulxh)
4373 DO_ZPZZ_FP(sve_fmulx_s, uint32_t, H1_4, helper_vfp_mulxs)
4374 DO_ZPZZ_FP(sve_fmulx_d, uint64_t, H1_8, helper_vfp_mulxd)
4375 
4376 #undef DO_ZPZZ_FP
4377 
4378 /* Three-operand expander, with one scalar operand, controlled by
4379  * a predicate, with the extra float_status parameter.
4380  */
4381 #define DO_ZPZS_FP(NAME, TYPE, H, OP) \
4382 void HELPER(NAME)(void *vd, void *vn, void *vg, uint64_t scalar,  \
4383                   void *status, uint32_t desc)                    \
4384 {                                                                 \
4385     intptr_t i = simd_oprsz(desc);                                \
4386     uint64_t *g = vg;                                             \
4387     TYPE mm = scalar;                                             \
4388     do {                                                          \
4389         uint64_t pg = g[(i - 1) >> 6];                            \
4390         do {                                                      \
4391             i -= sizeof(TYPE);                                    \
4392             if (likely((pg >> (i & 63)) & 1)) {                   \
4393                 TYPE nn = *(TYPE *)(vn + H(i));                   \
4394                 *(TYPE *)(vd + H(i)) = OP(nn, mm, status);        \
4395             }                                                     \
4396         } while (i & 63);                                         \
4397     } while (i != 0);                                             \
4398 }
4399 
4400 DO_ZPZS_FP(sve_fadds_h, float16, H1_2, float16_add)
4401 DO_ZPZS_FP(sve_fadds_s, float32, H1_4, float32_add)
4402 DO_ZPZS_FP(sve_fadds_d, float64, H1_8, float64_add)
4403 
4404 DO_ZPZS_FP(sve_fsubs_h, float16, H1_2, float16_sub)
4405 DO_ZPZS_FP(sve_fsubs_s, float32, H1_4, float32_sub)
4406 DO_ZPZS_FP(sve_fsubs_d, float64, H1_8, float64_sub)
4407 
4408 DO_ZPZS_FP(sve_fmuls_h, float16, H1_2, float16_mul)
4409 DO_ZPZS_FP(sve_fmuls_s, float32, H1_4, float32_mul)
4410 DO_ZPZS_FP(sve_fmuls_d, float64, H1_8, float64_mul)
4411 
4412 static inline float16 subr_h(float16 a, float16 b, float_status *s)
4413 {
4414     return float16_sub(b, a, s);
4415 }
4416 
4417 static inline float32 subr_s(float32 a, float32 b, float_status *s)
4418 {
4419     return float32_sub(b, a, s);
4420 }
4421 
4422 static inline float64 subr_d(float64 a, float64 b, float_status *s)
4423 {
4424     return float64_sub(b, a, s);
4425 }
4426 
4427 DO_ZPZS_FP(sve_fsubrs_h, float16, H1_2, subr_h)
4428 DO_ZPZS_FP(sve_fsubrs_s, float32, H1_4, subr_s)
4429 DO_ZPZS_FP(sve_fsubrs_d, float64, H1_8, subr_d)
4430 
4431 DO_ZPZS_FP(sve_fmaxnms_h, float16, H1_2, float16_maxnum)
4432 DO_ZPZS_FP(sve_fmaxnms_s, float32, H1_4, float32_maxnum)
4433 DO_ZPZS_FP(sve_fmaxnms_d, float64, H1_8, float64_maxnum)
4434 
4435 DO_ZPZS_FP(sve_fminnms_h, float16, H1_2, float16_minnum)
4436 DO_ZPZS_FP(sve_fminnms_s, float32, H1_4, float32_minnum)
4437 DO_ZPZS_FP(sve_fminnms_d, float64, H1_8, float64_minnum)
4438 
4439 DO_ZPZS_FP(sve_fmaxs_h, float16, H1_2, float16_max)
4440 DO_ZPZS_FP(sve_fmaxs_s, float32, H1_4, float32_max)
4441 DO_ZPZS_FP(sve_fmaxs_d, float64, H1_8, float64_max)
4442 
4443 DO_ZPZS_FP(sve_fmins_h, float16, H1_2, float16_min)
4444 DO_ZPZS_FP(sve_fmins_s, float32, H1_4, float32_min)
4445 DO_ZPZS_FP(sve_fmins_d, float64, H1_8, float64_min)
4446 
4447 /* Fully general two-operand expander, controlled by a predicate,
4448  * With the extra float_status parameter.
4449  */
4450 #define DO_ZPZ_FP(NAME, TYPE, H, OP)                                  \
4451 void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc) \
4452 {                                                                     \
4453     intptr_t i = simd_oprsz(desc);                                    \
4454     uint64_t *g = vg;                                                 \
4455     do {                                                              \
4456         uint64_t pg = g[(i - 1) >> 6];                                \
4457         do {                                                          \
4458             i -= sizeof(TYPE);                                        \
4459             if (likely((pg >> (i & 63)) & 1)) {                       \
4460                 TYPE nn = *(TYPE *)(vn + H(i));                       \
4461                 *(TYPE *)(vd + H(i)) = OP(nn, status);                \
4462             }                                                         \
4463         } while (i & 63);                                             \
4464     } while (i != 0);                                                 \
4465 }
4466 
4467 /* SVE fp16 conversions always use IEEE mode.  Like AdvSIMD, they ignore
4468  * FZ16.  When converting from fp16, this affects flushing input denormals;
4469  * when converting to fp16, this affects flushing output denormals.
4470  */
4471 static inline float32 sve_f16_to_f32(float16 f, float_status *fpst)
4472 {
4473     bool save = get_flush_inputs_to_zero(fpst);
4474     float32 ret;
4475 
4476     set_flush_inputs_to_zero(false, fpst);
4477     ret = float16_to_float32(f, true, fpst);
4478     set_flush_inputs_to_zero(save, fpst);
4479     return ret;
4480 }
4481 
4482 static inline float64 sve_f16_to_f64(float16 f, float_status *fpst)
4483 {
4484     bool save = get_flush_inputs_to_zero(fpst);
4485     float64 ret;
4486 
4487     set_flush_inputs_to_zero(false, fpst);
4488     ret = float16_to_float64(f, true, fpst);
4489     set_flush_inputs_to_zero(save, fpst);
4490     return ret;
4491 }
4492 
4493 static inline float16 sve_f32_to_f16(float32 f, float_status *fpst)
4494 {
4495     bool save = get_flush_to_zero(fpst);
4496     float16 ret;
4497 
4498     set_flush_to_zero(false, fpst);
4499     ret = float32_to_float16(f, true, fpst);
4500     set_flush_to_zero(save, fpst);
4501     return ret;
4502 }
4503 
4504 static inline float16 sve_f64_to_f16(float64 f, float_status *fpst)
4505 {
4506     bool save = get_flush_to_zero(fpst);
4507     float16 ret;
4508 
4509     set_flush_to_zero(false, fpst);
4510     ret = float64_to_float16(f, true, fpst);
4511     set_flush_to_zero(save, fpst);
4512     return ret;
4513 }
4514 
4515 static inline int16_t vfp_float16_to_int16_rtz(float16 f, float_status *s)
4516 {
4517     if (float16_is_any_nan(f)) {
4518         float_raise(float_flag_invalid, s);
4519         return 0;
4520     }
4521     return float16_to_int16_round_to_zero(f, s);
4522 }
4523 
4524 static inline int64_t vfp_float16_to_int64_rtz(float16 f, float_status *s)
4525 {
4526     if (float16_is_any_nan(f)) {
4527         float_raise(float_flag_invalid, s);
4528         return 0;
4529     }
4530     return float16_to_int64_round_to_zero(f, s);
4531 }
4532 
4533 static inline int64_t vfp_float32_to_int64_rtz(float32 f, float_status *s)
4534 {
4535     if (float32_is_any_nan(f)) {
4536         float_raise(float_flag_invalid, s);
4537         return 0;
4538     }
4539     return float32_to_int64_round_to_zero(f, s);
4540 }
4541 
4542 static inline int64_t vfp_float64_to_int64_rtz(float64 f, float_status *s)
4543 {
4544     if (float64_is_any_nan(f)) {
4545         float_raise(float_flag_invalid, s);
4546         return 0;
4547     }
4548     return float64_to_int64_round_to_zero(f, s);
4549 }
4550 
4551 static inline uint16_t vfp_float16_to_uint16_rtz(float16 f, float_status *s)
4552 {
4553     if (float16_is_any_nan(f)) {
4554         float_raise(float_flag_invalid, s);
4555         return 0;
4556     }
4557     return float16_to_uint16_round_to_zero(f, s);
4558 }
4559 
4560 static inline uint64_t vfp_float16_to_uint64_rtz(float16 f, float_status *s)
4561 {
4562     if (float16_is_any_nan(f)) {
4563         float_raise(float_flag_invalid, s);
4564         return 0;
4565     }
4566     return float16_to_uint64_round_to_zero(f, s);
4567 }
4568 
4569 static inline uint64_t vfp_float32_to_uint64_rtz(float32 f, float_status *s)
4570 {
4571     if (float32_is_any_nan(f)) {
4572         float_raise(float_flag_invalid, s);
4573         return 0;
4574     }
4575     return float32_to_uint64_round_to_zero(f, s);
4576 }
4577 
4578 static inline uint64_t vfp_float64_to_uint64_rtz(float64 f, float_status *s)
4579 {
4580     if (float64_is_any_nan(f)) {
4581         float_raise(float_flag_invalid, s);
4582         return 0;
4583     }
4584     return float64_to_uint64_round_to_zero(f, s);
4585 }
4586 
4587 DO_ZPZ_FP(sve_fcvt_sh, uint32_t, H1_4, sve_f32_to_f16)
4588 DO_ZPZ_FP(sve_fcvt_hs, uint32_t, H1_4, sve_f16_to_f32)
4589 DO_ZPZ_FP(sve_bfcvt,   uint32_t, H1_4, float32_to_bfloat16)
4590 DO_ZPZ_FP(sve_fcvt_dh, uint64_t, H1_8, sve_f64_to_f16)
4591 DO_ZPZ_FP(sve_fcvt_hd, uint64_t, H1_8, sve_f16_to_f64)
4592 DO_ZPZ_FP(sve_fcvt_ds, uint64_t, H1_8, float64_to_float32)
4593 DO_ZPZ_FP(sve_fcvt_sd, uint64_t, H1_8, float32_to_float64)
4594 
4595 DO_ZPZ_FP(sve_fcvtzs_hh, uint16_t, H1_2, vfp_float16_to_int16_rtz)
4596 DO_ZPZ_FP(sve_fcvtzs_hs, uint32_t, H1_4, helper_vfp_tosizh)
4597 DO_ZPZ_FP(sve_fcvtzs_ss, uint32_t, H1_4, helper_vfp_tosizs)
4598 DO_ZPZ_FP(sve_fcvtzs_hd, uint64_t, H1_8, vfp_float16_to_int64_rtz)
4599 DO_ZPZ_FP(sve_fcvtzs_sd, uint64_t, H1_8, vfp_float32_to_int64_rtz)
4600 DO_ZPZ_FP(sve_fcvtzs_ds, uint64_t, H1_8, helper_vfp_tosizd)
4601 DO_ZPZ_FP(sve_fcvtzs_dd, uint64_t, H1_8, vfp_float64_to_int64_rtz)
4602 
4603 DO_ZPZ_FP(sve_fcvtzu_hh, uint16_t, H1_2, vfp_float16_to_uint16_rtz)
4604 DO_ZPZ_FP(sve_fcvtzu_hs, uint32_t, H1_4, helper_vfp_touizh)
4605 DO_ZPZ_FP(sve_fcvtzu_ss, uint32_t, H1_4, helper_vfp_touizs)
4606 DO_ZPZ_FP(sve_fcvtzu_hd, uint64_t, H1_8, vfp_float16_to_uint64_rtz)
4607 DO_ZPZ_FP(sve_fcvtzu_sd, uint64_t, H1_8, vfp_float32_to_uint64_rtz)
4608 DO_ZPZ_FP(sve_fcvtzu_ds, uint64_t, H1_8, helper_vfp_touizd)
4609 DO_ZPZ_FP(sve_fcvtzu_dd, uint64_t, H1_8, vfp_float64_to_uint64_rtz)
4610 
4611 DO_ZPZ_FP(sve_frint_h, uint16_t, H1_2, helper_advsimd_rinth)
4612 DO_ZPZ_FP(sve_frint_s, uint32_t, H1_4, helper_rints)
4613 DO_ZPZ_FP(sve_frint_d, uint64_t, H1_8, helper_rintd)
4614 
4615 DO_ZPZ_FP(sve_frintx_h, uint16_t, H1_2, float16_round_to_int)
4616 DO_ZPZ_FP(sve_frintx_s, uint32_t, H1_4, float32_round_to_int)
4617 DO_ZPZ_FP(sve_frintx_d, uint64_t, H1_8, float64_round_to_int)
4618 
4619 DO_ZPZ_FP(sve_frecpx_h, uint16_t, H1_2, helper_frecpx_f16)
4620 DO_ZPZ_FP(sve_frecpx_s, uint32_t, H1_4, helper_frecpx_f32)
4621 DO_ZPZ_FP(sve_frecpx_d, uint64_t, H1_8, helper_frecpx_f64)
4622 
4623 DO_ZPZ_FP(sve_fsqrt_h, uint16_t, H1_2, float16_sqrt)
4624 DO_ZPZ_FP(sve_fsqrt_s, uint32_t, H1_4, float32_sqrt)
4625 DO_ZPZ_FP(sve_fsqrt_d, uint64_t, H1_8, float64_sqrt)
4626 
4627 DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16)
4628 DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16)
4629 DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32)
4630 DO_ZPZ_FP(sve_scvt_sd, uint64_t, H1_8, int32_to_float64)
4631 DO_ZPZ_FP(sve_scvt_dh, uint64_t, H1_8, int64_to_float16)
4632 DO_ZPZ_FP(sve_scvt_ds, uint64_t, H1_8, int64_to_float32)
4633 DO_ZPZ_FP(sve_scvt_dd, uint64_t, H1_8, int64_to_float64)
4634 
4635 DO_ZPZ_FP(sve_ucvt_hh, uint16_t, H1_2, uint16_to_float16)
4636 DO_ZPZ_FP(sve_ucvt_sh, uint32_t, H1_4, uint32_to_float16)
4637 DO_ZPZ_FP(sve_ucvt_ss, uint32_t, H1_4, uint32_to_float32)
4638 DO_ZPZ_FP(sve_ucvt_sd, uint64_t, H1_8, uint32_to_float64)
4639 DO_ZPZ_FP(sve_ucvt_dh, uint64_t, H1_8, uint64_to_float16)
4640 DO_ZPZ_FP(sve_ucvt_ds, uint64_t, H1_8, uint64_to_float32)
4641 DO_ZPZ_FP(sve_ucvt_dd, uint64_t, H1_8, uint64_to_float64)
4642 
4643 static int16_t do_float16_logb_as_int(float16 a, float_status *s)
4644 {
4645     /* Extract frac to the top of the uint32_t. */
4646     uint32_t frac = (uint32_t)a << (16 + 6);
4647     int16_t exp = extract32(a, 10, 5);
4648 
4649     if (unlikely(exp == 0)) {
4650         if (frac != 0) {
4651             if (!get_flush_inputs_to_zero(s)) {
4652                 /* denormal: bias - fractional_zeros */
4653                 return -15 - clz32(frac);
4654             }
4655             /* flush to zero */
4656             float_raise(float_flag_input_denormal, s);
4657         }
4658     } else if (unlikely(exp == 0x1f)) {
4659         if (frac == 0) {
4660             return INT16_MAX; /* infinity */
4661         }
4662     } else {
4663         /* normal: exp - bias */
4664         return exp - 15;
4665     }
4666     /* nan or zero */
4667     float_raise(float_flag_invalid, s);
4668     return INT16_MIN;
4669 }
4670 
4671 static int32_t do_float32_logb_as_int(float32 a, float_status *s)
4672 {
4673     /* Extract frac to the top of the uint32_t. */
4674     uint32_t frac = a << 9;
4675     int32_t exp = extract32(a, 23, 8);
4676 
4677     if (unlikely(exp == 0)) {
4678         if (frac != 0) {
4679             if (!get_flush_inputs_to_zero(s)) {
4680                 /* denormal: bias - fractional_zeros */
4681                 return -127 - clz32(frac);
4682             }
4683             /* flush to zero */
4684             float_raise(float_flag_input_denormal, s);
4685         }
4686     } else if (unlikely(exp == 0xff)) {
4687         if (frac == 0) {
4688             return INT32_MAX; /* infinity */
4689         }
4690     } else {
4691         /* normal: exp - bias */
4692         return exp - 127;
4693     }
4694     /* nan or zero */
4695     float_raise(float_flag_invalid, s);
4696     return INT32_MIN;
4697 }
4698 
4699 static int64_t do_float64_logb_as_int(float64 a, float_status *s)
4700 {
4701     /* Extract frac to the top of the uint64_t. */
4702     uint64_t frac = a << 12;
4703     int64_t exp = extract64(a, 52, 11);
4704 
4705     if (unlikely(exp == 0)) {
4706         if (frac != 0) {
4707             if (!get_flush_inputs_to_zero(s)) {
4708                 /* denormal: bias - fractional_zeros */
4709                 return -1023 - clz64(frac);
4710             }
4711             /* flush to zero */
4712             float_raise(float_flag_input_denormal, s);
4713         }
4714     } else if (unlikely(exp == 0x7ff)) {
4715         if (frac == 0) {
4716             return INT64_MAX; /* infinity */
4717         }
4718     } else {
4719         /* normal: exp - bias */
4720         return exp - 1023;
4721     }
4722     /* nan or zero */
4723     float_raise(float_flag_invalid, s);
4724     return INT64_MIN;
4725 }
4726 
4727 DO_ZPZ_FP(flogb_h, float16, H1_2, do_float16_logb_as_int)
4728 DO_ZPZ_FP(flogb_s, float32, H1_4, do_float32_logb_as_int)
4729 DO_ZPZ_FP(flogb_d, float64, H1_8, do_float64_logb_as_int)
4730 
4731 #undef DO_ZPZ_FP
4732 
4733 static void do_fmla_zpzzz_h(void *vd, void *vn, void *vm, void *va, void *vg,
4734                             float_status *status, uint32_t desc,
4735                             uint16_t neg1, uint16_t neg3)
4736 {
4737     intptr_t i = simd_oprsz(desc);
4738     uint64_t *g = vg;
4739 
4740     do {
4741         uint64_t pg = g[(i - 1) >> 6];
4742         do {
4743             i -= 2;
4744             if (likely((pg >> (i & 63)) & 1)) {
4745                 float16 e1, e2, e3, r;
4746 
4747                 e1 = *(uint16_t *)(vn + H1_2(i)) ^ neg1;
4748                 e2 = *(uint16_t *)(vm + H1_2(i));
4749                 e3 = *(uint16_t *)(va + H1_2(i)) ^ neg3;
4750                 r = float16_muladd(e1, e2, e3, 0, status);
4751                 *(uint16_t *)(vd + H1_2(i)) = r;
4752             }
4753         } while (i & 63);
4754     } while (i != 0);
4755 }
4756 
4757 void HELPER(sve_fmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va,
4758                               void *vg, void *status, uint32_t desc)
4759 {
4760     do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0, 0);
4761 }
4762 
4763 void HELPER(sve_fmls_zpzzz_h)(void *vd, void *vn, void *vm, void *va,
4764                               void *vg, void *status, uint32_t desc)
4765 {
4766     do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0x8000, 0);
4767 }
4768 
4769 void HELPER(sve_fnmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va,
4770                                void *vg, void *status, uint32_t desc)
4771 {
4772     do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0x8000, 0x8000);
4773 }
4774 
4775 void HELPER(sve_fnmls_zpzzz_h)(void *vd, void *vn, void *vm, void *va,
4776                                void *vg, void *status, uint32_t desc)
4777 {
4778     do_fmla_zpzzz_h(vd, vn, vm, va, vg, status, desc, 0, 0x8000);
4779 }
4780 
4781 static void do_fmla_zpzzz_s(void *vd, void *vn, void *vm, void *va, void *vg,
4782                             float_status *status, uint32_t desc,
4783                             uint32_t neg1, uint32_t neg3)
4784 {
4785     intptr_t i = simd_oprsz(desc);
4786     uint64_t *g = vg;
4787 
4788     do {
4789         uint64_t pg = g[(i - 1) >> 6];
4790         do {
4791             i -= 4;
4792             if (likely((pg >> (i & 63)) & 1)) {
4793                 float32 e1, e2, e3, r;
4794 
4795                 e1 = *(uint32_t *)(vn + H1_4(i)) ^ neg1;
4796                 e2 = *(uint32_t *)(vm + H1_4(i));
4797                 e3 = *(uint32_t *)(va + H1_4(i)) ^ neg3;
4798                 r = float32_muladd(e1, e2, e3, 0, status);
4799                 *(uint32_t *)(vd + H1_4(i)) = r;
4800             }
4801         } while (i & 63);
4802     } while (i != 0);
4803 }
4804 
4805 void HELPER(sve_fmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va,
4806                               void *vg, void *status, uint32_t desc)
4807 {
4808     do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0, 0);
4809 }
4810 
4811 void HELPER(sve_fmls_zpzzz_s)(void *vd, void *vn, void *vm, void *va,
4812                               void *vg, void *status, uint32_t desc)
4813 {
4814     do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0x80000000, 0);
4815 }
4816 
4817 void HELPER(sve_fnmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va,
4818                                void *vg, void *status, uint32_t desc)
4819 {
4820     do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0x80000000, 0x80000000);
4821 }
4822 
4823 void HELPER(sve_fnmls_zpzzz_s)(void *vd, void *vn, void *vm, void *va,
4824                                void *vg, void *status, uint32_t desc)
4825 {
4826     do_fmla_zpzzz_s(vd, vn, vm, va, vg, status, desc, 0, 0x80000000);
4827 }
4828 
4829 static void do_fmla_zpzzz_d(void *vd, void *vn, void *vm, void *va, void *vg,
4830                             float_status *status, uint32_t desc,
4831                             uint64_t neg1, uint64_t neg3)
4832 {
4833     intptr_t i = simd_oprsz(desc);
4834     uint64_t *g = vg;
4835 
4836     do {
4837         uint64_t pg = g[(i - 1) >> 6];
4838         do {
4839             i -= 8;
4840             if (likely((pg >> (i & 63)) & 1)) {
4841                 float64 e1, e2, e3, r;
4842 
4843                 e1 = *(uint64_t *)(vn + i) ^ neg1;
4844                 e2 = *(uint64_t *)(vm + i);
4845                 e3 = *(uint64_t *)(va + i) ^ neg3;
4846                 r = float64_muladd(e1, e2, e3, 0, status);
4847                 *(uint64_t *)(vd + i) = r;
4848             }
4849         } while (i & 63);
4850     } while (i != 0);
4851 }
4852 
4853 void HELPER(sve_fmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va,
4854                               void *vg, void *status, uint32_t desc)
4855 {
4856     do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, 0, 0);
4857 }
4858 
4859 void HELPER(sve_fmls_zpzzz_d)(void *vd, void *vn, void *vm, void *va,
4860                               void *vg, void *status, uint32_t desc)
4861 {
4862     do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, INT64_MIN, 0);
4863 }
4864 
4865 void HELPER(sve_fnmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va,
4866                                void *vg, void *status, uint32_t desc)
4867 {
4868     do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, INT64_MIN, INT64_MIN);
4869 }
4870 
4871 void HELPER(sve_fnmls_zpzzz_d)(void *vd, void *vn, void *vm, void *va,
4872                                void *vg, void *status, uint32_t desc)
4873 {
4874     do_fmla_zpzzz_d(vd, vn, vm, va, vg, status, desc, 0, INT64_MIN);
4875 }
4876 
4877 /* Two operand floating-point comparison controlled by a predicate.
4878  * Unlike the integer version, we are not allowed to optimistically
4879  * compare operands, since the comparison may have side effects wrt
4880  * the FPSR.
4881  */
4882 #define DO_FPCMP_PPZZ(NAME, TYPE, H, OP)                                \
4883 void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg,               \
4884                   void *status, uint32_t desc)                          \
4885 {                                                                       \
4886     intptr_t i = simd_oprsz(desc), j = (i - 1) >> 6;                    \
4887     uint64_t *d = vd, *g = vg;                                          \
4888     do {                                                                \
4889         uint64_t out = 0, pg = g[j];                                    \
4890         do {                                                            \
4891             i -= sizeof(TYPE), out <<= sizeof(TYPE);                    \
4892             if (likely((pg >> (i & 63)) & 1)) {                         \
4893                 TYPE nn = *(TYPE *)(vn + H(i));                         \
4894                 TYPE mm = *(TYPE *)(vm + H(i));                         \
4895                 out |= OP(TYPE, nn, mm, status);                        \
4896             }                                                           \
4897         } while (i & 63);                                               \
4898         d[j--] = out;                                                   \
4899     } while (i > 0);                                                    \
4900 }
4901 
4902 #define DO_FPCMP_PPZZ_H(NAME, OP) \
4903     DO_FPCMP_PPZZ(NAME##_h, float16, H1_2, OP)
4904 #define DO_FPCMP_PPZZ_S(NAME, OP) \
4905     DO_FPCMP_PPZZ(NAME##_s, float32, H1_4, OP)
4906 #define DO_FPCMP_PPZZ_D(NAME, OP) \
4907     DO_FPCMP_PPZZ(NAME##_d, float64, H1_8, OP)
4908 
4909 #define DO_FPCMP_PPZZ_ALL(NAME, OP) \
4910     DO_FPCMP_PPZZ_H(NAME, OP)   \
4911     DO_FPCMP_PPZZ_S(NAME, OP)   \
4912     DO_FPCMP_PPZZ_D(NAME, OP)
4913 
4914 #define DO_FCMGE(TYPE, X, Y, ST)  TYPE##_compare(Y, X, ST) <= 0
4915 #define DO_FCMGT(TYPE, X, Y, ST)  TYPE##_compare(Y, X, ST) < 0
4916 #define DO_FCMLE(TYPE, X, Y, ST)  TYPE##_compare(X, Y, ST) <= 0
4917 #define DO_FCMLT(TYPE, X, Y, ST)  TYPE##_compare(X, Y, ST) < 0
4918 #define DO_FCMEQ(TYPE, X, Y, ST)  TYPE##_compare_quiet(X, Y, ST) == 0
4919 #define DO_FCMNE(TYPE, X, Y, ST)  TYPE##_compare_quiet(X, Y, ST) != 0
4920 #define DO_FCMUO(TYPE, X, Y, ST)  \
4921     TYPE##_compare_quiet(X, Y, ST) == float_relation_unordered
4922 #define DO_FACGE(TYPE, X, Y, ST)  \
4923     TYPE##_compare(TYPE##_abs(Y), TYPE##_abs(X), ST) <= 0
4924 #define DO_FACGT(TYPE, X, Y, ST)  \
4925     TYPE##_compare(TYPE##_abs(Y), TYPE##_abs(X), ST) < 0
4926 
4927 DO_FPCMP_PPZZ_ALL(sve_fcmge, DO_FCMGE)
4928 DO_FPCMP_PPZZ_ALL(sve_fcmgt, DO_FCMGT)
4929 DO_FPCMP_PPZZ_ALL(sve_fcmeq, DO_FCMEQ)
4930 DO_FPCMP_PPZZ_ALL(sve_fcmne, DO_FCMNE)
4931 DO_FPCMP_PPZZ_ALL(sve_fcmuo, DO_FCMUO)
4932 DO_FPCMP_PPZZ_ALL(sve_facge, DO_FACGE)
4933 DO_FPCMP_PPZZ_ALL(sve_facgt, DO_FACGT)
4934 
4935 #undef DO_FPCMP_PPZZ_ALL
4936 #undef DO_FPCMP_PPZZ_D
4937 #undef DO_FPCMP_PPZZ_S
4938 #undef DO_FPCMP_PPZZ_H
4939 #undef DO_FPCMP_PPZZ
4940 
4941 /* One operand floating-point comparison against zero, controlled
4942  * by a predicate.
4943  */
4944 #define DO_FPCMP_PPZ0(NAME, TYPE, H, OP)                   \
4945 void HELPER(NAME)(void *vd, void *vn, void *vg,            \
4946                   void *status, uint32_t desc)             \
4947 {                                                          \
4948     intptr_t i = simd_oprsz(desc), j = (i - 1) >> 6;       \
4949     uint64_t *d = vd, *g = vg;                             \
4950     do {                                                   \
4951         uint64_t out = 0, pg = g[j];                       \
4952         do {                                               \
4953             i -= sizeof(TYPE), out <<= sizeof(TYPE);       \
4954             if ((pg >> (i & 63)) & 1) {                    \
4955                 TYPE nn = *(TYPE *)(vn + H(i));            \
4956                 out |= OP(TYPE, nn, 0, status);            \
4957             }                                              \
4958         } while (i & 63);                                  \
4959         d[j--] = out;                                      \
4960     } while (i > 0);                                       \
4961 }
4962 
4963 #define DO_FPCMP_PPZ0_H(NAME, OP) \
4964     DO_FPCMP_PPZ0(NAME##_h, float16, H1_2, OP)
4965 #define DO_FPCMP_PPZ0_S(NAME, OP) \
4966     DO_FPCMP_PPZ0(NAME##_s, float32, H1_4, OP)
4967 #define DO_FPCMP_PPZ0_D(NAME, OP) \
4968     DO_FPCMP_PPZ0(NAME##_d, float64, H1_8, OP)
4969 
4970 #define DO_FPCMP_PPZ0_ALL(NAME, OP) \
4971     DO_FPCMP_PPZ0_H(NAME, OP)   \
4972     DO_FPCMP_PPZ0_S(NAME, OP)   \
4973     DO_FPCMP_PPZ0_D(NAME, OP)
4974 
4975 DO_FPCMP_PPZ0_ALL(sve_fcmge0, DO_FCMGE)
4976 DO_FPCMP_PPZ0_ALL(sve_fcmgt0, DO_FCMGT)
4977 DO_FPCMP_PPZ0_ALL(sve_fcmle0, DO_FCMLE)
4978 DO_FPCMP_PPZ0_ALL(sve_fcmlt0, DO_FCMLT)
4979 DO_FPCMP_PPZ0_ALL(sve_fcmeq0, DO_FCMEQ)
4980 DO_FPCMP_PPZ0_ALL(sve_fcmne0, DO_FCMNE)
4981 
4982 /* FP Trig Multiply-Add. */
4983 
4984 void HELPER(sve_ftmad_h)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
4985 {
4986     static const float16 coeff[16] = {
4987         0x3c00, 0xb155, 0x2030, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
4988         0x3c00, 0xb800, 0x293a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
4989     };
4990     intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float16);
4991     intptr_t x = simd_data(desc);
4992     float16 *d = vd, *n = vn, *m = vm;
4993     for (i = 0; i < opr_sz; i++) {
4994         float16 mm = m[i];
4995         intptr_t xx = x;
4996         if (float16_is_neg(mm)) {
4997             mm = float16_abs(mm);
4998             xx += 8;
4999         }
5000         d[i] = float16_muladd(n[i], mm, coeff[xx], 0, vs);
5001     }
5002 }
5003 
5004 void HELPER(sve_ftmad_s)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
5005 {
5006     static const float32 coeff[16] = {
5007         0x3f800000, 0xbe2aaaab, 0x3c088886, 0xb95008b9,
5008         0x36369d6d, 0x00000000, 0x00000000, 0x00000000,
5009         0x3f800000, 0xbf000000, 0x3d2aaaa6, 0xbab60705,
5010         0x37cd37cc, 0x00000000, 0x00000000, 0x00000000,
5011     };
5012     intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float32);
5013     intptr_t x = simd_data(desc);
5014     float32 *d = vd, *n = vn, *m = vm;
5015     for (i = 0; i < opr_sz; i++) {
5016         float32 mm = m[i];
5017         intptr_t xx = x;
5018         if (float32_is_neg(mm)) {
5019             mm = float32_abs(mm);
5020             xx += 8;
5021         }
5022         d[i] = float32_muladd(n[i], mm, coeff[xx], 0, vs);
5023     }
5024 }
5025 
5026 void HELPER(sve_ftmad_d)(void *vd, void *vn, void *vm, void *vs, uint32_t desc)
5027 {
5028     static const float64 coeff[16] = {
5029         0x3ff0000000000000ull, 0xbfc5555555555543ull,
5030         0x3f8111111110f30cull, 0xbf2a01a019b92fc6ull,
5031         0x3ec71de351f3d22bull, 0xbe5ae5e2b60f7b91ull,
5032         0x3de5d8408868552full, 0x0000000000000000ull,
5033         0x3ff0000000000000ull, 0xbfe0000000000000ull,
5034         0x3fa5555555555536ull, 0xbf56c16c16c13a0bull,
5035         0x3efa01a019b1e8d8ull, 0xbe927e4f7282f468ull,
5036         0x3e21ee96d2641b13ull, 0xbda8f76380fbb401ull,
5037     };
5038     intptr_t i, opr_sz = simd_oprsz(desc) / sizeof(float64);
5039     intptr_t x = simd_data(desc);
5040     float64 *d = vd, *n = vn, *m = vm;
5041     for (i = 0; i < opr_sz; i++) {
5042         float64 mm = m[i];
5043         intptr_t xx = x;
5044         if (float64_is_neg(mm)) {
5045             mm = float64_abs(mm);
5046             xx += 8;
5047         }
5048         d[i] = float64_muladd(n[i], mm, coeff[xx], 0, vs);
5049     }
5050 }
5051 
5052 /*
5053  * FP Complex Add
5054  */
5055 
5056 void HELPER(sve_fcadd_h)(void *vd, void *vn, void *vm, void *vg,
5057                          void *vs, uint32_t desc)
5058 {
5059     intptr_t j, i = simd_oprsz(desc);
5060     uint64_t *g = vg;
5061     float16 neg_imag = float16_set_sign(0, simd_data(desc));
5062     float16 neg_real = float16_chs(neg_imag);
5063 
5064     do {
5065         uint64_t pg = g[(i - 1) >> 6];
5066         do {
5067             float16 e0, e1, e2, e3;
5068 
5069             /* I holds the real index; J holds the imag index.  */
5070             j = i - sizeof(float16);
5071             i -= 2 * sizeof(float16);
5072 
5073             e0 = *(float16 *)(vn + H1_2(i));
5074             e1 = *(float16 *)(vm + H1_2(j)) ^ neg_real;
5075             e2 = *(float16 *)(vn + H1_2(j));
5076             e3 = *(float16 *)(vm + H1_2(i)) ^ neg_imag;
5077 
5078             if (likely((pg >> (i & 63)) & 1)) {
5079                 *(float16 *)(vd + H1_2(i)) = float16_add(e0, e1, vs);
5080             }
5081             if (likely((pg >> (j & 63)) & 1)) {
5082                 *(float16 *)(vd + H1_2(j)) = float16_add(e2, e3, vs);
5083             }
5084         } while (i & 63);
5085     } while (i != 0);
5086 }
5087 
5088 void HELPER(sve_fcadd_s)(void *vd, void *vn, void *vm, void *vg,
5089                          void *vs, uint32_t desc)
5090 {
5091     intptr_t j, i = simd_oprsz(desc);
5092     uint64_t *g = vg;
5093     float32 neg_imag = float32_set_sign(0, simd_data(desc));
5094     float32 neg_real = float32_chs(neg_imag);
5095 
5096     do {
5097         uint64_t pg = g[(i - 1) >> 6];
5098         do {
5099             float32 e0, e1, e2, e3;
5100 
5101             /* I holds the real index; J holds the imag index.  */
5102             j = i - sizeof(float32);
5103             i -= 2 * sizeof(float32);
5104 
5105             e0 = *(float32 *)(vn + H1_2(i));
5106             e1 = *(float32 *)(vm + H1_2(j)) ^ neg_real;
5107             e2 = *(float32 *)(vn + H1_2(j));
5108             e3 = *(float32 *)(vm + H1_2(i)) ^ neg_imag;
5109 
5110             if (likely((pg >> (i & 63)) & 1)) {
5111                 *(float32 *)(vd + H1_2(i)) = float32_add(e0, e1, vs);
5112             }
5113             if (likely((pg >> (j & 63)) & 1)) {
5114                 *(float32 *)(vd + H1_2(j)) = float32_add(e2, e3, vs);
5115             }
5116         } while (i & 63);
5117     } while (i != 0);
5118 }
5119 
5120 void HELPER(sve_fcadd_d)(void *vd, void *vn, void *vm, void *vg,
5121                          void *vs, uint32_t desc)
5122 {
5123     intptr_t j, i = simd_oprsz(desc);
5124     uint64_t *g = vg;
5125     float64 neg_imag = float64_set_sign(0, simd_data(desc));
5126     float64 neg_real = float64_chs(neg_imag);
5127 
5128     do {
5129         uint64_t pg = g[(i - 1) >> 6];
5130         do {
5131             float64 e0, e1, e2, e3;
5132 
5133             /* I holds the real index; J holds the imag index.  */
5134             j = i - sizeof(float64);
5135             i -= 2 * sizeof(float64);
5136 
5137             e0 = *(float64 *)(vn + H1_2(i));
5138             e1 = *(float64 *)(vm + H1_2(j)) ^ neg_real;
5139             e2 = *(float64 *)(vn + H1_2(j));
5140             e3 = *(float64 *)(vm + H1_2(i)) ^ neg_imag;
5141 
5142             if (likely((pg >> (i & 63)) & 1)) {
5143                 *(float64 *)(vd + H1_2(i)) = float64_add(e0, e1, vs);
5144             }
5145             if (likely((pg >> (j & 63)) & 1)) {
5146                 *(float64 *)(vd + H1_2(j)) = float64_add(e2, e3, vs);
5147             }
5148         } while (i & 63);
5149     } while (i != 0);
5150 }
5151 
5152 /*
5153  * FP Complex Multiply
5154  */
5155 
5156 void HELPER(sve_fcmla_zpzzz_h)(void *vd, void *vn, void *vm, void *va,
5157                                void *vg, void *status, uint32_t desc)
5158 {
5159     intptr_t j, i = simd_oprsz(desc);
5160     unsigned rot = simd_data(desc);
5161     bool flip = rot & 1;
5162     float16 neg_imag, neg_real;
5163     uint64_t *g = vg;
5164 
5165     neg_imag = float16_set_sign(0, (rot & 2) != 0);
5166     neg_real = float16_set_sign(0, rot == 1 || rot == 2);
5167 
5168     do {
5169         uint64_t pg = g[(i - 1) >> 6];
5170         do {
5171             float16 e1, e2, e3, e4, nr, ni, mr, mi, d;
5172 
5173             /* I holds the real index; J holds the imag index.  */
5174             j = i - sizeof(float16);
5175             i -= 2 * sizeof(float16);
5176 
5177             nr = *(float16 *)(vn + H1_2(i));
5178             ni = *(float16 *)(vn + H1_2(j));
5179             mr = *(float16 *)(vm + H1_2(i));
5180             mi = *(float16 *)(vm + H1_2(j));
5181 
5182             e2 = (flip ? ni : nr);
5183             e1 = (flip ? mi : mr) ^ neg_real;
5184             e4 = e2;
5185             e3 = (flip ? mr : mi) ^ neg_imag;
5186 
5187             if (likely((pg >> (i & 63)) & 1)) {
5188                 d = *(float16 *)(va + H1_2(i));
5189                 d = float16_muladd(e2, e1, d, 0, status);
5190                 *(float16 *)(vd + H1_2(i)) = d;
5191             }
5192             if (likely((pg >> (j & 63)) & 1)) {
5193                 d = *(float16 *)(va + H1_2(j));
5194                 d = float16_muladd(e4, e3, d, 0, status);
5195                 *(float16 *)(vd + H1_2(j)) = d;
5196             }
5197         } while (i & 63);
5198     } while (i != 0);
5199 }
5200 
5201 void HELPER(sve_fcmla_zpzzz_s)(void *vd, void *vn, void *vm, void *va,
5202                                void *vg, void *status, uint32_t desc)
5203 {
5204     intptr_t j, i = simd_oprsz(desc);
5205     unsigned rot = simd_data(desc);
5206     bool flip = rot & 1;
5207     float32 neg_imag, neg_real;
5208     uint64_t *g = vg;
5209 
5210     neg_imag = float32_set_sign(0, (rot & 2) != 0);
5211     neg_real = float32_set_sign(0, rot == 1 || rot == 2);
5212 
5213     do {
5214         uint64_t pg = g[(i - 1) >> 6];
5215         do {
5216             float32 e1, e2, e3, e4, nr, ni, mr, mi, d;
5217 
5218             /* I holds the real index; J holds the imag index.  */
5219             j = i - sizeof(float32);
5220             i -= 2 * sizeof(float32);
5221 
5222             nr = *(float32 *)(vn + H1_2(i));
5223             ni = *(float32 *)(vn + H1_2(j));
5224             mr = *(float32 *)(vm + H1_2(i));
5225             mi = *(float32 *)(vm + H1_2(j));
5226 
5227             e2 = (flip ? ni : nr);
5228             e1 = (flip ? mi : mr) ^ neg_real;
5229             e4 = e2;
5230             e3 = (flip ? mr : mi) ^ neg_imag;
5231 
5232             if (likely((pg >> (i & 63)) & 1)) {
5233                 d = *(float32 *)(va + H1_2(i));
5234                 d = float32_muladd(e2, e1, d, 0, status);
5235                 *(float32 *)(vd + H1_2(i)) = d;
5236             }
5237             if (likely((pg >> (j & 63)) & 1)) {
5238                 d = *(float32 *)(va + H1_2(j));
5239                 d = float32_muladd(e4, e3, d, 0, status);
5240                 *(float32 *)(vd + H1_2(j)) = d;
5241             }
5242         } while (i & 63);
5243     } while (i != 0);
5244 }
5245 
5246 void HELPER(sve_fcmla_zpzzz_d)(void *vd, void *vn, void *vm, void *va,
5247                                void *vg, void *status, uint32_t desc)
5248 {
5249     intptr_t j, i = simd_oprsz(desc);
5250     unsigned rot = simd_data(desc);
5251     bool flip = rot & 1;
5252     float64 neg_imag, neg_real;
5253     uint64_t *g = vg;
5254 
5255     neg_imag = float64_set_sign(0, (rot & 2) != 0);
5256     neg_real = float64_set_sign(0, rot == 1 || rot == 2);
5257 
5258     do {
5259         uint64_t pg = g[(i - 1) >> 6];
5260         do {
5261             float64 e1, e2, e3, e4, nr, ni, mr, mi, d;
5262 
5263             /* I holds the real index; J holds the imag index.  */
5264             j = i - sizeof(float64);
5265             i -= 2 * sizeof(float64);
5266 
5267             nr = *(float64 *)(vn + H1_2(i));
5268             ni = *(float64 *)(vn + H1_2(j));
5269             mr = *(float64 *)(vm + H1_2(i));
5270             mi = *(float64 *)(vm + H1_2(j));
5271 
5272             e2 = (flip ? ni : nr);
5273             e1 = (flip ? mi : mr) ^ neg_real;
5274             e4 = e2;
5275             e3 = (flip ? mr : mi) ^ neg_imag;
5276 
5277             if (likely((pg >> (i & 63)) & 1)) {
5278                 d = *(float64 *)(va + H1_2(i));
5279                 d = float64_muladd(e2, e1, d, 0, status);
5280                 *(float64 *)(vd + H1_2(i)) = d;
5281             }
5282             if (likely((pg >> (j & 63)) & 1)) {
5283                 d = *(float64 *)(va + H1_2(j));
5284                 d = float64_muladd(e4, e3, d, 0, status);
5285                 *(float64 *)(vd + H1_2(j)) = d;
5286             }
5287         } while (i & 63);
5288     } while (i != 0);
5289 }
5290 
5291 /*
5292  * Load contiguous data, protected by a governing predicate.
5293  */
5294 
5295 /*
5296  * Skip through a sequence of inactive elements in the guarding predicate @vg,
5297  * beginning at @reg_off bounded by @reg_max.  Return the offset of the active
5298  * element >= @reg_off, or @reg_max if there were no active elements at all.
5299  */
5300 static intptr_t find_next_active(uint64_t *vg, intptr_t reg_off,
5301                                  intptr_t reg_max, int esz)
5302 {
5303     uint64_t pg_mask = pred_esz_masks[esz];
5304     uint64_t pg = (vg[reg_off >> 6] & pg_mask) >> (reg_off & 63);
5305 
5306     /* In normal usage, the first element is active.  */
5307     if (likely(pg & 1)) {
5308         return reg_off;
5309     }
5310 
5311     if (pg == 0) {
5312         reg_off &= -64;
5313         do {
5314             reg_off += 64;
5315             if (unlikely(reg_off >= reg_max)) {
5316                 /* The entire predicate was false.  */
5317                 return reg_max;
5318             }
5319             pg = vg[reg_off >> 6] & pg_mask;
5320         } while (pg == 0);
5321     }
5322     reg_off += ctz64(pg);
5323 
5324     /* We should never see an out of range predicate bit set.  */
5325     tcg_debug_assert(reg_off < reg_max);
5326     return reg_off;
5327 }
5328 
5329 /*
5330  * Resolve the guest virtual address to info->host and info->flags.
5331  * If @nofault, return false if the page is invalid, otherwise
5332  * exit via page fault exception.
5333  */
5334 
5335 bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
5336                     target_ulong addr, int mem_off, MMUAccessType access_type,
5337                     int mmu_idx, uintptr_t retaddr)
5338 {
5339     int flags;
5340 
5341     addr += mem_off;
5342 
5343     /*
5344      * User-only currently always issues with TBI.  See the comment
5345      * above useronly_clean_ptr.  Usually we clean this top byte away
5346      * during translation, but we can't do that for e.g. vector + imm
5347      * addressing modes.
5348      *
5349      * We currently always enable TBI for user-only, and do not provide
5350      * a way to turn it off.  So clean the pointer unconditionally here,
5351      * rather than look it up here, or pass it down from above.
5352      */
5353     addr = useronly_clean_ptr(addr);
5354 
5355 #ifdef CONFIG_USER_ONLY
5356     flags = probe_access_flags(env, addr, 0, access_type, mmu_idx, nofault,
5357                                &info->host, retaddr);
5358 #else
5359     CPUTLBEntryFull *full;
5360     flags = probe_access_full(env, addr, 0, access_type, mmu_idx, nofault,
5361                               &info->host, &full, retaddr);
5362 #endif
5363     info->flags = flags;
5364 
5365     if (flags & TLB_INVALID_MASK) {
5366         g_assert(nofault);
5367         return false;
5368     }
5369 
5370 #ifdef CONFIG_USER_ONLY
5371     memset(&info->attrs, 0, sizeof(info->attrs));
5372     /* Require both ANON and MTE; see allocation_tag_mem(). */
5373     info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
5374 #else
5375     info->attrs = full->attrs;
5376     info->tagged = full->extra.arm.pte_attrs == 0xf0;
5377 #endif
5378 
5379     /* Ensure that info->host[] is relative to addr, not addr + mem_off. */
5380     info->host -= mem_off;
5381     return true;
5382 }
5383 
5384 /*
5385  * Find first active element on each page, and a loose bound for the
5386  * final element on each page.  Identify any single element that spans
5387  * the page boundary.  Return true if there are any active elements.
5388  */
5389 bool sve_cont_ldst_elements(SVEContLdSt *info, target_ulong addr, uint64_t *vg,
5390                             intptr_t reg_max, int esz, int msize)
5391 {
5392     const int esize = 1 << esz;
5393     const uint64_t pg_mask = pred_esz_masks[esz];
5394     intptr_t reg_off_first = -1, reg_off_last = -1, reg_off_split;
5395     intptr_t mem_off_last, mem_off_split;
5396     intptr_t page_split, elt_split;
5397     intptr_t i;
5398 
5399     /* Set all of the element indices to -1, and the TLB data to 0. */
5400     memset(info, -1, offsetof(SVEContLdSt, page));
5401     memset(info->page, 0, sizeof(info->page));
5402 
5403     /* Gross scan over the entire predicate to find bounds. */
5404     i = 0;
5405     do {
5406         uint64_t pg = vg[i] & pg_mask;
5407         if (pg) {
5408             reg_off_last = i * 64 + 63 - clz64(pg);
5409             if (reg_off_first < 0) {
5410                 reg_off_first = i * 64 + ctz64(pg);
5411             }
5412         }
5413     } while (++i * 64 < reg_max);
5414 
5415     if (unlikely(reg_off_first < 0)) {
5416         /* No active elements, no pages touched. */
5417         return false;
5418     }
5419     tcg_debug_assert(reg_off_last >= 0 && reg_off_last < reg_max);
5420 
5421     info->reg_off_first[0] = reg_off_first;
5422     info->mem_off_first[0] = (reg_off_first >> esz) * msize;
5423     mem_off_last = (reg_off_last >> esz) * msize;
5424 
5425     page_split = -(addr | TARGET_PAGE_MASK);
5426     if (likely(mem_off_last + msize <= page_split)) {
5427         /* The entire operation fits within a single page. */
5428         info->reg_off_last[0] = reg_off_last;
5429         return true;
5430     }
5431 
5432     info->page_split = page_split;
5433     elt_split = page_split / msize;
5434     reg_off_split = elt_split << esz;
5435     mem_off_split = elt_split * msize;
5436 
5437     /*
5438      * This is the last full element on the first page, but it is not
5439      * necessarily active.  If there is no full element, i.e. the first
5440      * active element is the one that's split, this value remains -1.
5441      * It is useful as iteration bounds.
5442      */
5443     if (elt_split != 0) {
5444         info->reg_off_last[0] = reg_off_split - esize;
5445     }
5446 
5447     /* Determine if an unaligned element spans the pages.  */
5448     if (page_split % msize != 0) {
5449         /* It is helpful to know if the split element is active. */
5450         if ((vg[reg_off_split >> 6] >> (reg_off_split & 63)) & 1) {
5451             info->reg_off_split = reg_off_split;
5452             info->mem_off_split = mem_off_split;
5453 
5454             if (reg_off_split == reg_off_last) {
5455                 /* The page crossing element is last. */
5456                 return true;
5457             }
5458         }
5459         reg_off_split += esize;
5460         mem_off_split += msize;
5461     }
5462 
5463     /*
5464      * We do want the first active element on the second page, because
5465      * this may affect the address reported in an exception.
5466      */
5467     reg_off_split = find_next_active(vg, reg_off_split, reg_max, esz);
5468     tcg_debug_assert(reg_off_split <= reg_off_last);
5469     info->reg_off_first[1] = reg_off_split;
5470     info->mem_off_first[1] = (reg_off_split >> esz) * msize;
5471     info->reg_off_last[1] = reg_off_last;
5472     return true;
5473 }
5474 
5475 /*
5476  * Resolve the guest virtual addresses to info->page[].
5477  * Control the generation of page faults with @fault.  Return false if
5478  * there is no work to do, which can only happen with @fault == FAULT_NO.
5479  */
5480 bool sve_cont_ldst_pages(SVEContLdSt *info, SVEContFault fault,
5481                          CPUARMState *env, target_ulong addr,
5482                          MMUAccessType access_type, uintptr_t retaddr)
5483 {
5484     int mmu_idx = arm_env_mmu_index(env);
5485     int mem_off = info->mem_off_first[0];
5486     bool nofault = fault == FAULT_NO;
5487     bool have_work = true;
5488 
5489     if (!sve_probe_page(&info->page[0], nofault, env, addr, mem_off,
5490                         access_type, mmu_idx, retaddr)) {
5491         /* No work to be done. */
5492         return false;
5493     }
5494 
5495     if (likely(info->page_split < 0)) {
5496         /* The entire operation was on the one page. */
5497         return true;
5498     }
5499 
5500     /*
5501      * If the second page is invalid, then we want the fault address to be
5502      * the first byte on that page which is accessed.
5503      */
5504     if (info->mem_off_split >= 0) {
5505         /*
5506          * There is an element split across the pages.  The fault address
5507          * should be the first byte of the second page.
5508          */
5509         mem_off = info->page_split;
5510         /*
5511          * If the split element is also the first active element
5512          * of the vector, then:  For first-fault we should continue
5513          * to generate faults for the second page.  For no-fault,
5514          * we have work only if the second page is valid.
5515          */
5516         if (info->mem_off_first[0] < info->mem_off_split) {
5517             nofault = FAULT_FIRST;
5518             have_work = false;
5519         }
5520     } else {
5521         /*
5522          * There is no element split across the pages.  The fault address
5523          * should be the first active element on the second page.
5524          */
5525         mem_off = info->mem_off_first[1];
5526         /*
5527          * There must have been one active element on the first page,
5528          * so we're out of first-fault territory.
5529          */
5530         nofault = fault != FAULT_ALL;
5531     }
5532 
5533     have_work |= sve_probe_page(&info->page[1], nofault, env, addr, mem_off,
5534                                 access_type, mmu_idx, retaddr);
5535     return have_work;
5536 }
5537 
5538 #ifndef CONFIG_USER_ONLY
5539 void sve_cont_ldst_watchpoints(SVEContLdSt *info, CPUARMState *env,
5540                                uint64_t *vg, target_ulong addr,
5541                                int esize, int msize, int wp_access,
5542                                uintptr_t retaddr)
5543 {
5544     intptr_t mem_off, reg_off, reg_last;
5545     int flags0 = info->page[0].flags;
5546     int flags1 = info->page[1].flags;
5547 
5548     if (likely(!((flags0 | flags1) & TLB_WATCHPOINT))) {
5549         return;
5550     }
5551 
5552     /* Indicate that watchpoints are handled. */
5553     info->page[0].flags = flags0 & ~TLB_WATCHPOINT;
5554     info->page[1].flags = flags1 & ~TLB_WATCHPOINT;
5555 
5556     if (flags0 & TLB_WATCHPOINT) {
5557         mem_off = info->mem_off_first[0];
5558         reg_off = info->reg_off_first[0];
5559         reg_last = info->reg_off_last[0];
5560 
5561         while (reg_off <= reg_last) {
5562             uint64_t pg = vg[reg_off >> 6];
5563             do {
5564                 if ((pg >> (reg_off & 63)) & 1) {
5565                     cpu_check_watchpoint(env_cpu(env), addr + mem_off,
5566                                          msize, info->page[0].attrs,
5567                                          wp_access, retaddr);
5568                 }
5569                 reg_off += esize;
5570                 mem_off += msize;
5571             } while (reg_off <= reg_last && (reg_off & 63));
5572         }
5573     }
5574 
5575     mem_off = info->mem_off_split;
5576     if (mem_off >= 0) {
5577         cpu_check_watchpoint(env_cpu(env), addr + mem_off, msize,
5578                              info->page[0].attrs, wp_access, retaddr);
5579     }
5580 
5581     mem_off = info->mem_off_first[1];
5582     if ((flags1 & TLB_WATCHPOINT) && mem_off >= 0) {
5583         reg_off = info->reg_off_first[1];
5584         reg_last = info->reg_off_last[1];
5585 
5586         do {
5587             uint64_t pg = vg[reg_off >> 6];
5588             do {
5589                 if ((pg >> (reg_off & 63)) & 1) {
5590                     cpu_check_watchpoint(env_cpu(env), addr + mem_off,
5591                                          msize, info->page[1].attrs,
5592                                          wp_access, retaddr);
5593                 }
5594                 reg_off += esize;
5595                 mem_off += msize;
5596             } while (reg_off & 63);
5597         } while (reg_off <= reg_last);
5598     }
5599 }
5600 #endif
5601 
5602 void sve_cont_ldst_mte_check(SVEContLdSt *info, CPUARMState *env,
5603                              uint64_t *vg, target_ulong addr, int esize,
5604                              int msize, uint32_t mtedesc, uintptr_t ra)
5605 {
5606     intptr_t mem_off, reg_off, reg_last;
5607 
5608     /* Process the page only if MemAttr == Tagged. */
5609     if (info->page[0].tagged) {
5610         mem_off = info->mem_off_first[0];
5611         reg_off = info->reg_off_first[0];
5612         reg_last = info->reg_off_split;
5613         if (reg_last < 0) {
5614             reg_last = info->reg_off_last[0];
5615         }
5616 
5617         do {
5618             uint64_t pg = vg[reg_off >> 6];
5619             do {
5620                 if ((pg >> (reg_off & 63)) & 1) {
5621                     mte_check(env, mtedesc, addr, ra);
5622                 }
5623                 reg_off += esize;
5624                 mem_off += msize;
5625             } while (reg_off <= reg_last && (reg_off & 63));
5626         } while (reg_off <= reg_last);
5627     }
5628 
5629     mem_off = info->mem_off_first[1];
5630     if (mem_off >= 0 && info->page[1].tagged) {
5631         reg_off = info->reg_off_first[1];
5632         reg_last = info->reg_off_last[1];
5633 
5634         do {
5635             uint64_t pg = vg[reg_off >> 6];
5636             do {
5637                 if ((pg >> (reg_off & 63)) & 1) {
5638                     mte_check(env, mtedesc, addr, ra);
5639                 }
5640                 reg_off += esize;
5641                 mem_off += msize;
5642             } while (reg_off & 63);
5643         } while (reg_off <= reg_last);
5644     }
5645 }
5646 
5647 /*
5648  * Common helper for all contiguous 1,2,3,4-register predicated stores.
5649  */
5650 static inline QEMU_ALWAYS_INLINE
5651 void sve_ldN_r(CPUARMState *env, uint64_t *vg, const target_ulong addr,
5652                uint32_t desc, const uintptr_t retaddr,
5653                const int esz, const int msz, const int N, uint32_t mtedesc,
5654                sve_ldst1_host_fn *host_fn,
5655                sve_ldst1_tlb_fn *tlb_fn)
5656 {
5657     const unsigned rd = simd_data(desc);
5658     const intptr_t reg_max = simd_oprsz(desc);
5659     intptr_t reg_off, reg_last, mem_off;
5660     SVEContLdSt info;
5661     void *host;
5662     int flags, i;
5663 
5664     /* Find the active elements.  */
5665     if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, N << msz)) {
5666         /* The entire predicate was false; no load occurs.  */
5667         for (i = 0; i < N; ++i) {
5668             memset(&env->vfp.zregs[(rd + i) & 31], 0, reg_max);
5669         }
5670         return;
5671     }
5672 
5673     /* Probe the page(s).  Exit with exception for any invalid page. */
5674     sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_LOAD, retaddr);
5675 
5676     /* Handle watchpoints for all active elements. */
5677     sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz,
5678                               BP_MEM_READ, retaddr);
5679 
5680     /*
5681      * Handle mte checks for all active elements.
5682      * Since TBI must be set for MTE, !mtedesc => !mte_active.
5683      */
5684     if (mtedesc) {
5685         sve_cont_ldst_mte_check(&info, env, vg, addr, 1 << esz, N << msz,
5686                                 mtedesc, retaddr);
5687     }
5688 
5689     flags = info.page[0].flags | info.page[1].flags;
5690     if (unlikely(flags != 0)) {
5691         /*
5692          * At least one page includes MMIO.
5693          * Any bus operation can fail with cpu_transaction_failed,
5694          * which for ARM will raise SyncExternal.  Perform the load
5695          * into scratch memory to preserve register state until the end.
5696          */
5697         ARMVectorReg scratch[4] = { };
5698 
5699         mem_off = info.mem_off_first[0];
5700         reg_off = info.reg_off_first[0];
5701         reg_last = info.reg_off_last[1];
5702         if (reg_last < 0) {
5703             reg_last = info.reg_off_split;
5704             if (reg_last < 0) {
5705                 reg_last = info.reg_off_last[0];
5706             }
5707         }
5708 
5709         do {
5710             uint64_t pg = vg[reg_off >> 6];
5711             do {
5712                 if ((pg >> (reg_off & 63)) & 1) {
5713                     for (i = 0; i < N; ++i) {
5714                         tlb_fn(env, &scratch[i], reg_off,
5715                                addr + mem_off + (i << msz), retaddr);
5716                     }
5717                 }
5718                 reg_off += 1 << esz;
5719                 mem_off += N << msz;
5720             } while (reg_off & 63);
5721         } while (reg_off <= reg_last);
5722 
5723         for (i = 0; i < N; ++i) {
5724             memcpy(&env->vfp.zregs[(rd + i) & 31], &scratch[i], reg_max);
5725         }
5726         return;
5727     }
5728 
5729     /* The entire operation is in RAM, on valid pages. */
5730 
5731     for (i = 0; i < N; ++i) {
5732         memset(&env->vfp.zregs[(rd + i) & 31], 0, reg_max);
5733     }
5734 
5735     mem_off = info.mem_off_first[0];
5736     reg_off = info.reg_off_first[0];
5737     reg_last = info.reg_off_last[0];
5738     host = info.page[0].host;
5739 
5740     while (reg_off <= reg_last) {
5741         uint64_t pg = vg[reg_off >> 6];
5742         do {
5743             if ((pg >> (reg_off & 63)) & 1) {
5744                 for (i = 0; i < N; ++i) {
5745                     host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off,
5746                             host + mem_off + (i << msz));
5747                 }
5748             }
5749             reg_off += 1 << esz;
5750             mem_off += N << msz;
5751         } while (reg_off <= reg_last && (reg_off & 63));
5752     }
5753 
5754     /*
5755      * Use the slow path to manage the cross-page misalignment.
5756      * But we know this is RAM and cannot trap.
5757      */
5758     mem_off = info.mem_off_split;
5759     if (unlikely(mem_off >= 0)) {
5760         reg_off = info.reg_off_split;
5761         for (i = 0; i < N; ++i) {
5762             tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off,
5763                    addr + mem_off + (i << msz), retaddr);
5764         }
5765     }
5766 
5767     mem_off = info.mem_off_first[1];
5768     if (unlikely(mem_off >= 0)) {
5769         reg_off = info.reg_off_first[1];
5770         reg_last = info.reg_off_last[1];
5771         host = info.page[1].host;
5772 
5773         do {
5774             uint64_t pg = vg[reg_off >> 6];
5775             do {
5776                 if ((pg >> (reg_off & 63)) & 1) {
5777                     for (i = 0; i < N; ++i) {
5778                         host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off,
5779                                 host + mem_off + (i << msz));
5780                     }
5781                 }
5782                 reg_off += 1 << esz;
5783                 mem_off += N << msz;
5784             } while (reg_off & 63);
5785         } while (reg_off <= reg_last);
5786     }
5787 }
5788 
5789 static inline QEMU_ALWAYS_INLINE
5790 void sve_ldN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
5791                    uint32_t desc, const uintptr_t ra,
5792                    const int esz, const int msz, const int N,
5793                    sve_ldst1_host_fn *host_fn,
5794                    sve_ldst1_tlb_fn *tlb_fn)
5795 {
5796     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
5797     int bit55 = extract64(addr, 55, 1);
5798 
5799     /* Remove mtedesc from the normal sve descriptor. */
5800     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
5801 
5802     /* Perform gross MTE suppression early. */
5803     if (!tbi_check(desc, bit55) ||
5804         tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
5805         mtedesc = 0;
5806     }
5807 
5808     sve_ldN_r(env, vg, addr, desc, ra, esz, msz, N, mtedesc, host_fn, tlb_fn);
5809 }
5810 
5811 #define DO_LD1_1(NAME, ESZ)                                             \
5812 void HELPER(sve_##NAME##_r)(CPUARMState *env, void *vg,                 \
5813                             target_ulong addr, uint32_t desc)           \
5814 {                                                                       \
5815     sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1, 0,            \
5816               sve_##NAME##_host, sve_##NAME##_tlb);                     \
5817 }                                                                       \
5818 void HELPER(sve_##NAME##_r_mte)(CPUARMState *env, void *vg,             \
5819                                 target_ulong addr, uint32_t desc)       \
5820 {                                                                       \
5821     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, 1,           \
5822                   sve_##NAME##_host, sve_##NAME##_tlb);                 \
5823 }
5824 
5825 #define DO_LD1_2(NAME, ESZ, MSZ)                                        \
5826 void HELPER(sve_##NAME##_le_r)(CPUARMState *env, void *vg,              \
5827                                target_ulong addr, uint32_t desc)        \
5828 {                                                                       \
5829     sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, 0,             \
5830               sve_##NAME##_le_host, sve_##NAME##_le_tlb);               \
5831 }                                                                       \
5832 void HELPER(sve_##NAME##_be_r)(CPUARMState *env, void *vg,              \
5833                                target_ulong addr, uint32_t desc)        \
5834 {                                                                       \
5835     sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1, 0,             \
5836               sve_##NAME##_be_host, sve_##NAME##_be_tlb);               \
5837 }                                                                       \
5838 void HELPER(sve_##NAME##_le_r_mte)(CPUARMState *env, void *vg,          \
5839                                    target_ulong addr, uint32_t desc)    \
5840 {                                                                       \
5841     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1,            \
5842                   sve_##NAME##_le_host, sve_##NAME##_le_tlb);           \
5843 }                                                                       \
5844 void HELPER(sve_##NAME##_be_r_mte)(CPUARMState *env, void *vg,          \
5845                                    target_ulong addr, uint32_t desc)    \
5846 {                                                                       \
5847     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, 1,            \
5848                   sve_##NAME##_be_host, sve_##NAME##_be_tlb);           \
5849 }
5850 
5851 DO_LD1_1(ld1bb,  MO_8)
5852 DO_LD1_1(ld1bhu, MO_16)
5853 DO_LD1_1(ld1bhs, MO_16)
5854 DO_LD1_1(ld1bsu, MO_32)
5855 DO_LD1_1(ld1bss, MO_32)
5856 DO_LD1_1(ld1bdu, MO_64)
5857 DO_LD1_1(ld1bds, MO_64)
5858 
5859 DO_LD1_2(ld1hh,  MO_16, MO_16)
5860 DO_LD1_2(ld1hsu, MO_32, MO_16)
5861 DO_LD1_2(ld1hss, MO_32, MO_16)
5862 DO_LD1_2(ld1hdu, MO_64, MO_16)
5863 DO_LD1_2(ld1hds, MO_64, MO_16)
5864 
5865 DO_LD1_2(ld1ss,  MO_32, MO_32)
5866 DO_LD1_2(ld1sdu, MO_64, MO_32)
5867 DO_LD1_2(ld1sds, MO_64, MO_32)
5868 
5869 DO_LD1_2(ld1dd,  MO_64, MO_64)
5870 
5871 #undef DO_LD1_1
5872 #undef DO_LD1_2
5873 
5874 #define DO_LDN_1(N)                                                     \
5875 void HELPER(sve_ld##N##bb_r)(CPUARMState *env, void *vg,                \
5876                              target_ulong addr, uint32_t desc)          \
5877 {                                                                       \
5878     sve_ldN_r(env, vg, addr, desc, GETPC(), MO_8, MO_8, N, 0,           \
5879               sve_ld1bb_host, sve_ld1bb_tlb);                           \
5880 }                                                                       \
5881 void HELPER(sve_ld##N##bb_r_mte)(CPUARMState *env, void *vg,            \
5882                                  target_ulong addr, uint32_t desc)      \
5883 {                                                                       \
5884     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), MO_8, MO_8, N,          \
5885                   sve_ld1bb_host, sve_ld1bb_tlb);                       \
5886 }
5887 
5888 #define DO_LDN_2(N, SUFF, ESZ)                                          \
5889 void HELPER(sve_ld##N##SUFF##_le_r)(CPUARMState *env, void *vg,         \
5890                                     target_ulong addr, uint32_t desc)   \
5891 {                                                                       \
5892     sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, 0,             \
5893               sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb);         \
5894 }                                                                       \
5895 void HELPER(sve_ld##N##SUFF##_be_r)(CPUARMState *env, void *vg,         \
5896                                     target_ulong addr, uint32_t desc)   \
5897 {                                                                       \
5898     sve_ldN_r(env, vg, addr, desc, GETPC(), ESZ, ESZ, N, 0,             \
5899               sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb);         \
5900 }                                                                       \
5901 void HELPER(sve_ld##N##SUFF##_le_r_mte)(CPUARMState *env, void *vg,     \
5902                                         target_ulong addr, uint32_t desc) \
5903 {                                                                       \
5904     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, ESZ, N,            \
5905                   sve_ld1##SUFF##_le_host, sve_ld1##SUFF##_le_tlb);     \
5906 }                                                                       \
5907 void HELPER(sve_ld##N##SUFF##_be_r_mte)(CPUARMState *env, void *vg,     \
5908                                         target_ulong addr, uint32_t desc) \
5909 {                                                                       \
5910     sve_ldN_r_mte(env, vg, addr, desc, GETPC(), ESZ, ESZ, N,            \
5911                   sve_ld1##SUFF##_be_host, sve_ld1##SUFF##_be_tlb);     \
5912 }
5913 
5914 DO_LDN_1(2)
5915 DO_LDN_1(3)
5916 DO_LDN_1(4)
5917 
5918 DO_LDN_2(2, hh, MO_16)
5919 DO_LDN_2(3, hh, MO_16)
5920 DO_LDN_2(4, hh, MO_16)
5921 
5922 DO_LDN_2(2, ss, MO_32)
5923 DO_LDN_2(3, ss, MO_32)
5924 DO_LDN_2(4, ss, MO_32)
5925 
5926 DO_LDN_2(2, dd, MO_64)
5927 DO_LDN_2(3, dd, MO_64)
5928 DO_LDN_2(4, dd, MO_64)
5929 
5930 #undef DO_LDN_1
5931 #undef DO_LDN_2
5932 
5933 /*
5934  * Load contiguous data, first-fault and no-fault.
5935  *
5936  * For user-only, one could argue that we should hold the mmap_lock during
5937  * the operation so that there is no race between page_check_range and the
5938  * load operation.  However, unmapping pages out from under a running thread
5939  * is extraordinarily unlikely.  This theoretical race condition also affects
5940  * linux-user/ in its get_user/put_user macros.
5941  *
5942  * TODO: Construct some helpers, written in assembly, that interact with
5943  * host_signal_handler to produce memory ops which can properly report errors
5944  * without racing.
5945  */
5946 
5947 /* Fault on byte I.  All bits in FFR from I are cleared.  The vector
5948  * result from I is CONSTRAINED UNPREDICTABLE; we choose the MERGE
5949  * option, which leaves subsequent data unchanged.
5950  */
5951 static void record_fault(CPUARMState *env, uintptr_t i, uintptr_t oprsz)
5952 {
5953     uint64_t *ffr = env->vfp.pregs[FFR_PRED_NUM].p;
5954 
5955     if (i & 63) {
5956         ffr[i / 64] &= MAKE_64BIT_MASK(0, i & 63);
5957         i = ROUND_UP(i, 64);
5958     }
5959     for (; i < oprsz; i += 64) {
5960         ffr[i / 64] = 0;
5961     }
5962 }
5963 
5964 /*
5965  * Common helper for all contiguous no-fault and first-fault loads.
5966  */
5967 static inline QEMU_ALWAYS_INLINE
5968 void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr,
5969                    uint32_t desc, const uintptr_t retaddr, uint32_t mtedesc,
5970                    const int esz, const int msz, const SVEContFault fault,
5971                    sve_ldst1_host_fn *host_fn,
5972                    sve_ldst1_tlb_fn *tlb_fn)
5973 {
5974     const unsigned rd = simd_data(desc);
5975     void *vd = &env->vfp.zregs[rd];
5976     const intptr_t reg_max = simd_oprsz(desc);
5977     intptr_t reg_off, mem_off, reg_last;
5978     SVEContLdSt info;
5979     int flags;
5980     void *host;
5981 
5982     /* Find the active elements.  */
5983     if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, 1 << msz)) {
5984         /* The entire predicate was false; no load occurs.  */
5985         memset(vd, 0, reg_max);
5986         return;
5987     }
5988     reg_off = info.reg_off_first[0];
5989 
5990     /* Probe the page(s). */
5991     if (!sve_cont_ldst_pages(&info, fault, env, addr, MMU_DATA_LOAD, retaddr)) {
5992         /* Fault on first element. */
5993         tcg_debug_assert(fault == FAULT_NO);
5994         memset(vd, 0, reg_max);
5995         goto do_fault;
5996     }
5997 
5998     mem_off = info.mem_off_first[0];
5999     flags = info.page[0].flags;
6000 
6001     /*
6002      * Disable MTE checking if the Tagged bit is not set.  Since TBI must
6003      * be set within MTEDESC for MTE, !mtedesc => !mte_active.
6004      */
6005     if (!info.page[0].tagged) {
6006         mtedesc = 0;
6007     }
6008 
6009     if (fault == FAULT_FIRST) {
6010         /* Trapping mte check for the first-fault element.  */
6011         if (mtedesc) {
6012             mte_check(env, mtedesc, addr + mem_off, retaddr);
6013         }
6014 
6015         /*
6016          * Special handling of the first active element,
6017          * if it crosses a page boundary or is MMIO.
6018          */
6019         bool is_split = mem_off == info.mem_off_split;
6020         if (unlikely(flags != 0) || unlikely(is_split)) {
6021             /*
6022              * Use the slow path for cross-page handling.
6023              * Might trap for MMIO or watchpoints.
6024              */
6025             tlb_fn(env, vd, reg_off, addr + mem_off, retaddr);
6026 
6027             /* After any fault, zero the other elements. */
6028             swap_memzero(vd, reg_off);
6029             reg_off += 1 << esz;
6030             mem_off += 1 << msz;
6031             swap_memzero(vd + reg_off, reg_max - reg_off);
6032 
6033             if (is_split) {
6034                 goto second_page;
6035             }
6036         } else {
6037             memset(vd, 0, reg_max);
6038         }
6039     } else {
6040         memset(vd, 0, reg_max);
6041         if (unlikely(mem_off == info.mem_off_split)) {
6042             /* The first active element crosses a page boundary. */
6043             flags |= info.page[1].flags;
6044             if (unlikely(flags & TLB_MMIO)) {
6045                 /* Some page is MMIO, see below. */
6046                 goto do_fault;
6047             }
6048             if (unlikely(flags & TLB_WATCHPOINT) &&
6049                 (cpu_watchpoint_address_matches
6050                  (env_cpu(env), addr + mem_off, 1 << msz)
6051                  & BP_MEM_READ)) {
6052                 /* Watchpoint hit, see below. */
6053                 goto do_fault;
6054             }
6055             if (mtedesc && !mte_probe(env, mtedesc, addr + mem_off)) {
6056                 goto do_fault;
6057             }
6058             /*
6059              * Use the slow path for cross-page handling.
6060              * This is RAM, without a watchpoint, and will not trap.
6061              */
6062             tlb_fn(env, vd, reg_off, addr + mem_off, retaddr);
6063             goto second_page;
6064         }
6065     }
6066 
6067     /*
6068      * From this point on, all memory operations are MemSingleNF.
6069      *
6070      * Per the MemSingleNF pseudocode, a no-fault load from Device memory
6071      * must not actually hit the bus -- it returns (UNKNOWN, FAULT) instead.
6072      *
6073      * Unfortuately we do not have access to the memory attributes from the
6074      * PTE to tell Device memory from Normal memory.  So we make a mostly
6075      * correct check, and indicate (UNKNOWN, FAULT) for any MMIO.
6076      * This gives the right answer for the common cases of "Normal memory,
6077      * backed by host RAM" and "Device memory, backed by MMIO".
6078      * The architecture allows us to suppress an NF load and return
6079      * (UNKNOWN, FAULT) for any reason, so our behaviour for the corner
6080      * case of "Normal memory, backed by MMIO" is permitted.  The case we
6081      * get wrong is "Device memory, backed by host RAM", for which we
6082      * should return (UNKNOWN, FAULT) for but do not.
6083      *
6084      * Similarly, CPU_BP breakpoints would raise exceptions, and so
6085      * return (UNKNOWN, FAULT).  For simplicity, we consider gdb and
6086      * architectural breakpoints the same.
6087      */
6088     if (unlikely(flags & TLB_MMIO)) {
6089         goto do_fault;
6090     }
6091 
6092     reg_last = info.reg_off_last[0];
6093     host = info.page[0].host;
6094 
6095     do {
6096         uint64_t pg = *(uint64_t *)(vg + (reg_off >> 3));
6097         do {
6098             if ((pg >> (reg_off & 63)) & 1) {
6099                 if (unlikely(flags & TLB_WATCHPOINT) &&
6100                     (cpu_watchpoint_address_matches
6101                      (env_cpu(env), addr + mem_off, 1 << msz)
6102                      & BP_MEM_READ)) {
6103                     goto do_fault;
6104                 }
6105                 if (mtedesc && !mte_probe(env, mtedesc, addr + mem_off)) {
6106                     goto do_fault;
6107                 }
6108                 host_fn(vd, reg_off, host + mem_off);
6109             }
6110             reg_off += 1 << esz;
6111             mem_off += 1 << msz;
6112         } while (reg_off <= reg_last && (reg_off & 63));
6113     } while (reg_off <= reg_last);
6114 
6115     /*
6116      * MemSingleNF is allowed to fail for any reason.  We have special
6117      * code above to handle the first element crossing a page boundary.
6118      * As an implementation choice, decline to handle a cross-page element
6119      * in any other position.
6120      */
6121     reg_off = info.reg_off_split;
6122     if (reg_off >= 0) {
6123         goto do_fault;
6124     }
6125 
6126  second_page:
6127     reg_off = info.reg_off_first[1];
6128     if (likely(reg_off < 0)) {
6129         /* No active elements on the second page.  All done. */
6130         return;
6131     }
6132 
6133     /*
6134      * MemSingleNF is allowed to fail for any reason.  As an implementation
6135      * choice, decline to handle elements on the second page.  This should
6136      * be low frequency as the guest walks through memory -- the next
6137      * iteration of the guest's loop should be aligned on the page boundary,
6138      * and then all following iterations will stay aligned.
6139      */
6140 
6141  do_fault:
6142     record_fault(env, reg_off, reg_max);
6143 }
6144 
6145 static inline QEMU_ALWAYS_INLINE
6146 void sve_ldnfff1_r_mte(CPUARMState *env, void *vg, target_ulong addr,
6147                        uint32_t desc, const uintptr_t retaddr,
6148                        const int esz, const int msz, const SVEContFault fault,
6149                        sve_ldst1_host_fn *host_fn,
6150                        sve_ldst1_tlb_fn *tlb_fn)
6151 {
6152     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6153     int bit55 = extract64(addr, 55, 1);
6154 
6155     /* Remove mtedesc from the normal sve descriptor. */
6156     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6157 
6158     /* Perform gross MTE suppression early. */
6159     if (!tbi_check(desc, bit55) ||
6160         tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
6161         mtedesc = 0;
6162     }
6163 
6164     sve_ldnfff1_r(env, vg, addr, desc, retaddr, mtedesc,
6165                   esz, msz, fault, host_fn, tlb_fn);
6166 }
6167 
6168 #define DO_LDFF1_LDNF1_1(PART, ESZ)                                     \
6169 void HELPER(sve_ldff1##PART##_r)(CPUARMState *env, void *vg,            \
6170                                  target_ulong addr, uint32_t desc)      \
6171 {                                                                       \
6172     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MO_8, FAULT_FIRST, \
6173                   sve_ld1##PART##_host, sve_ld1##PART##_tlb);           \
6174 }                                                                       \
6175 void HELPER(sve_ldnf1##PART##_r)(CPUARMState *env, void *vg,            \
6176                                  target_ulong addr, uint32_t desc)      \
6177 {                                                                       \
6178     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MO_8, FAULT_NO, \
6179                   sve_ld1##PART##_host, sve_ld1##PART##_tlb);           \
6180 }                                                                       \
6181 void HELPER(sve_ldff1##PART##_r_mte)(CPUARMState *env, void *vg,        \
6182                                      target_ulong addr, uint32_t desc)  \
6183 {                                                                       \
6184     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_FIRST, \
6185                       sve_ld1##PART##_host, sve_ld1##PART##_tlb);       \
6186 }                                                                       \
6187 void HELPER(sve_ldnf1##PART##_r_mte)(CPUARMState *env, void *vg,        \
6188                                      target_ulong addr, uint32_t desc)  \
6189 {                                                                       \
6190     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, FAULT_NO, \
6191                   sve_ld1##PART##_host, sve_ld1##PART##_tlb);           \
6192 }
6193 
6194 #define DO_LDFF1_LDNF1_2(PART, ESZ, MSZ)                                \
6195 void HELPER(sve_ldff1##PART##_le_r)(CPUARMState *env, void *vg,         \
6196                                     target_ulong addr, uint32_t desc)   \
6197 {                                                                       \
6198     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_FIRST, \
6199                   sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb);     \
6200 }                                                                       \
6201 void HELPER(sve_ldnf1##PART##_le_r)(CPUARMState *env, void *vg,         \
6202                                     target_ulong addr, uint32_t desc)   \
6203 {                                                                       \
6204     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_NO,  \
6205                   sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb);     \
6206 }                                                                       \
6207 void HELPER(sve_ldff1##PART##_be_r)(CPUARMState *env, void *vg,         \
6208                                     target_ulong addr, uint32_t desc)   \
6209 {                                                                       \
6210     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_FIRST, \
6211                   sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb);     \
6212 }                                                                       \
6213 void HELPER(sve_ldnf1##PART##_be_r)(CPUARMState *env, void *vg,         \
6214                                     target_ulong addr, uint32_t desc)   \
6215 {                                                                       \
6216     sve_ldnfff1_r(env, vg, addr, desc, GETPC(), 0, ESZ, MSZ, FAULT_NO,  \
6217                   sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb);     \
6218 }                                                                       \
6219 void HELPER(sve_ldff1##PART##_le_r_mte)(CPUARMState *env, void *vg,     \
6220                                         target_ulong addr, uint32_t desc) \
6221 {                                                                       \
6222     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \
6223                       sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
6224 }                                                                       \
6225 void HELPER(sve_ldnf1##PART##_le_r_mte)(CPUARMState *env, void *vg,     \
6226                                         target_ulong addr, uint32_t desc) \
6227 {                                                                       \
6228     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \
6229                       sve_ld1##PART##_le_host, sve_ld1##PART##_le_tlb); \
6230 }                                                                       \
6231 void HELPER(sve_ldff1##PART##_be_r_mte)(CPUARMState *env, void *vg,     \
6232                                         target_ulong addr, uint32_t desc) \
6233 {                                                                       \
6234     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_FIRST, \
6235                       sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
6236 }                                                                       \
6237 void HELPER(sve_ldnf1##PART##_be_r_mte)(CPUARMState *env, void *vg,     \
6238                                         target_ulong addr, uint32_t desc) \
6239 {                                                                       \
6240     sve_ldnfff1_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, FAULT_NO, \
6241                       sve_ld1##PART##_be_host, sve_ld1##PART##_be_tlb); \
6242 }
6243 
6244 DO_LDFF1_LDNF1_1(bb,  MO_8)
6245 DO_LDFF1_LDNF1_1(bhu, MO_16)
6246 DO_LDFF1_LDNF1_1(bhs, MO_16)
6247 DO_LDFF1_LDNF1_1(bsu, MO_32)
6248 DO_LDFF1_LDNF1_1(bss, MO_32)
6249 DO_LDFF1_LDNF1_1(bdu, MO_64)
6250 DO_LDFF1_LDNF1_1(bds, MO_64)
6251 
6252 DO_LDFF1_LDNF1_2(hh,  MO_16, MO_16)
6253 DO_LDFF1_LDNF1_2(hsu, MO_32, MO_16)
6254 DO_LDFF1_LDNF1_2(hss, MO_32, MO_16)
6255 DO_LDFF1_LDNF1_2(hdu, MO_64, MO_16)
6256 DO_LDFF1_LDNF1_2(hds, MO_64, MO_16)
6257 
6258 DO_LDFF1_LDNF1_2(ss,  MO_32, MO_32)
6259 DO_LDFF1_LDNF1_2(sdu, MO_64, MO_32)
6260 DO_LDFF1_LDNF1_2(sds, MO_64, MO_32)
6261 
6262 DO_LDFF1_LDNF1_2(dd,  MO_64, MO_64)
6263 
6264 #undef DO_LDFF1_LDNF1_1
6265 #undef DO_LDFF1_LDNF1_2
6266 
6267 /*
6268  * Common helper for all contiguous 1,2,3,4-register predicated stores.
6269  */
6270 
6271 static inline QEMU_ALWAYS_INLINE
6272 void sve_stN_r(CPUARMState *env, uint64_t *vg, target_ulong addr,
6273                uint32_t desc, const uintptr_t retaddr,
6274                const int esz, const int msz, const int N, uint32_t mtedesc,
6275                sve_ldst1_host_fn *host_fn,
6276                sve_ldst1_tlb_fn *tlb_fn)
6277 {
6278     const unsigned rd = simd_data(desc);
6279     const intptr_t reg_max = simd_oprsz(desc);
6280     intptr_t reg_off, reg_last, mem_off;
6281     SVEContLdSt info;
6282     void *host;
6283     int i, flags;
6284 
6285     /* Find the active elements.  */
6286     if (!sve_cont_ldst_elements(&info, addr, vg, reg_max, esz, N << msz)) {
6287         /* The entire predicate was false; no store occurs.  */
6288         return;
6289     }
6290 
6291     /* Probe the page(s).  Exit with exception for any invalid page. */
6292     sve_cont_ldst_pages(&info, FAULT_ALL, env, addr, MMU_DATA_STORE, retaddr);
6293 
6294     /* Handle watchpoints for all active elements. */
6295     sve_cont_ldst_watchpoints(&info, env, vg, addr, 1 << esz, N << msz,
6296                               BP_MEM_WRITE, retaddr);
6297 
6298     /*
6299      * Handle mte checks for all active elements.
6300      * Since TBI must be set for MTE, !mtedesc => !mte_active.
6301      */
6302     if (mtedesc) {
6303         sve_cont_ldst_mte_check(&info, env, vg, addr, 1 << esz, N << msz,
6304                                 mtedesc, retaddr);
6305     }
6306 
6307     flags = info.page[0].flags | info.page[1].flags;
6308     if (unlikely(flags != 0)) {
6309 #ifdef CONFIG_USER_ONLY
6310         g_assert_not_reached();
6311 #else
6312         /*
6313          * At least one page includes MMIO.
6314          * Any bus operation can fail with cpu_transaction_failed,
6315          * which for ARM will raise SyncExternal.  We cannot avoid
6316          * this fault and will leave with the store incomplete.
6317          */
6318         mem_off = info.mem_off_first[0];
6319         reg_off = info.reg_off_first[0];
6320         reg_last = info.reg_off_last[1];
6321         if (reg_last < 0) {
6322             reg_last = info.reg_off_split;
6323             if (reg_last < 0) {
6324                 reg_last = info.reg_off_last[0];
6325             }
6326         }
6327 
6328         do {
6329             uint64_t pg = vg[reg_off >> 6];
6330             do {
6331                 if ((pg >> (reg_off & 63)) & 1) {
6332                     for (i = 0; i < N; ++i) {
6333                         tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off,
6334                                addr + mem_off + (i << msz), retaddr);
6335                     }
6336                 }
6337                 reg_off += 1 << esz;
6338                 mem_off += N << msz;
6339             } while (reg_off & 63);
6340         } while (reg_off <= reg_last);
6341         return;
6342 #endif
6343     }
6344 
6345     mem_off = info.mem_off_first[0];
6346     reg_off = info.reg_off_first[0];
6347     reg_last = info.reg_off_last[0];
6348     host = info.page[0].host;
6349 
6350     while (reg_off <= reg_last) {
6351         uint64_t pg = vg[reg_off >> 6];
6352         do {
6353             if ((pg >> (reg_off & 63)) & 1) {
6354                 for (i = 0; i < N; ++i) {
6355                     host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off,
6356                             host + mem_off + (i << msz));
6357                 }
6358             }
6359             reg_off += 1 << esz;
6360             mem_off += N << msz;
6361         } while (reg_off <= reg_last && (reg_off & 63));
6362     }
6363 
6364     /*
6365      * Use the slow path to manage the cross-page misalignment.
6366      * But we know this is RAM and cannot trap.
6367      */
6368     mem_off = info.mem_off_split;
6369     if (unlikely(mem_off >= 0)) {
6370         reg_off = info.reg_off_split;
6371         for (i = 0; i < N; ++i) {
6372             tlb_fn(env, &env->vfp.zregs[(rd + i) & 31], reg_off,
6373                    addr + mem_off + (i << msz), retaddr);
6374         }
6375     }
6376 
6377     mem_off = info.mem_off_first[1];
6378     if (unlikely(mem_off >= 0)) {
6379         reg_off = info.reg_off_first[1];
6380         reg_last = info.reg_off_last[1];
6381         host = info.page[1].host;
6382 
6383         do {
6384             uint64_t pg = vg[reg_off >> 6];
6385             do {
6386                 if ((pg >> (reg_off & 63)) & 1) {
6387                     for (i = 0; i < N; ++i) {
6388                         host_fn(&env->vfp.zregs[(rd + i) & 31], reg_off,
6389                                 host + mem_off + (i << msz));
6390                     }
6391                 }
6392                 reg_off += 1 << esz;
6393                 mem_off += N << msz;
6394             } while (reg_off & 63);
6395         } while (reg_off <= reg_last);
6396     }
6397 }
6398 
6399 static inline QEMU_ALWAYS_INLINE
6400 void sve_stN_r_mte(CPUARMState *env, uint64_t *vg, target_ulong addr,
6401                    uint32_t desc, const uintptr_t ra,
6402                    const int esz, const int msz, const int N,
6403                    sve_ldst1_host_fn *host_fn,
6404                    sve_ldst1_tlb_fn *tlb_fn)
6405 {
6406     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6407     int bit55 = extract64(addr, 55, 1);
6408 
6409     /* Remove mtedesc from the normal sve descriptor. */
6410     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6411 
6412     /* Perform gross MTE suppression early. */
6413     if (!tbi_check(desc, bit55) ||
6414         tcma_check(desc, bit55, allocation_tag_from_addr(addr))) {
6415         mtedesc = 0;
6416     }
6417 
6418     sve_stN_r(env, vg, addr, desc, ra, esz, msz, N, mtedesc, host_fn, tlb_fn);
6419 }
6420 
6421 #define DO_STN_1(N, NAME, ESZ)                                          \
6422 void HELPER(sve_st##N##NAME##_r)(CPUARMState *env, void *vg,            \
6423                                  target_ulong addr, uint32_t desc)      \
6424 {                                                                       \
6425     sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MO_8, N, 0,            \
6426               sve_st1##NAME##_host, sve_st1##NAME##_tlb);               \
6427 }                                                                       \
6428 void HELPER(sve_st##N##NAME##_r_mte)(CPUARMState *env, void *vg,        \
6429                                      target_ulong addr, uint32_t desc)  \
6430 {                                                                       \
6431     sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MO_8, N,           \
6432                   sve_st1##NAME##_host, sve_st1##NAME##_tlb);           \
6433 }
6434 
6435 #define DO_STN_2(N, NAME, ESZ, MSZ)                                     \
6436 void HELPER(sve_st##N##NAME##_le_r)(CPUARMState *env, void *vg,         \
6437                                     target_ulong addr, uint32_t desc)   \
6438 {                                                                       \
6439     sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, 0,             \
6440               sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb);         \
6441 }                                                                       \
6442 void HELPER(sve_st##N##NAME##_be_r)(CPUARMState *env, void *vg,         \
6443                                     target_ulong addr, uint32_t desc)   \
6444 {                                                                       \
6445     sve_stN_r(env, vg, addr, desc, GETPC(), ESZ, MSZ, N, 0,             \
6446               sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb);         \
6447 }                                                                       \
6448 void HELPER(sve_st##N##NAME##_le_r_mte)(CPUARMState *env, void *vg,     \
6449                                         target_ulong addr, uint32_t desc) \
6450 {                                                                       \
6451     sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, N,            \
6452                   sve_st1##NAME##_le_host, sve_st1##NAME##_le_tlb);     \
6453 }                                                                       \
6454 void HELPER(sve_st##N##NAME##_be_r_mte)(CPUARMState *env, void *vg,     \
6455                                         target_ulong addr, uint32_t desc) \
6456 {                                                                       \
6457     sve_stN_r_mte(env, vg, addr, desc, GETPC(), ESZ, MSZ, N,            \
6458                   sve_st1##NAME##_be_host, sve_st1##NAME##_be_tlb);     \
6459 }
6460 
6461 DO_STN_1(1, bb, MO_8)
6462 DO_STN_1(1, bh, MO_16)
6463 DO_STN_1(1, bs, MO_32)
6464 DO_STN_1(1, bd, MO_64)
6465 DO_STN_1(2, bb, MO_8)
6466 DO_STN_1(3, bb, MO_8)
6467 DO_STN_1(4, bb, MO_8)
6468 
6469 DO_STN_2(1, hh, MO_16, MO_16)
6470 DO_STN_2(1, hs, MO_32, MO_16)
6471 DO_STN_2(1, hd, MO_64, MO_16)
6472 DO_STN_2(2, hh, MO_16, MO_16)
6473 DO_STN_2(3, hh, MO_16, MO_16)
6474 DO_STN_2(4, hh, MO_16, MO_16)
6475 
6476 DO_STN_2(1, ss, MO_32, MO_32)
6477 DO_STN_2(1, sd, MO_64, MO_32)
6478 DO_STN_2(2, ss, MO_32, MO_32)
6479 DO_STN_2(3, ss, MO_32, MO_32)
6480 DO_STN_2(4, ss, MO_32, MO_32)
6481 
6482 DO_STN_2(1, dd, MO_64, MO_64)
6483 DO_STN_2(2, dd, MO_64, MO_64)
6484 DO_STN_2(3, dd, MO_64, MO_64)
6485 DO_STN_2(4, dd, MO_64, MO_64)
6486 
6487 #undef DO_STN_1
6488 #undef DO_STN_2
6489 
6490 /*
6491  * Loads with a vector index.
6492  */
6493 
6494 /*
6495  * Load the element at @reg + @reg_ofs, sign or zero-extend as needed.
6496  */
6497 typedef target_ulong zreg_off_fn(void *reg, intptr_t reg_ofs);
6498 
6499 static target_ulong off_zsu_s(void *reg, intptr_t reg_ofs)
6500 {
6501     return *(uint32_t *)(reg + H1_4(reg_ofs));
6502 }
6503 
6504 static target_ulong off_zss_s(void *reg, intptr_t reg_ofs)
6505 {
6506     return *(int32_t *)(reg + H1_4(reg_ofs));
6507 }
6508 
6509 static target_ulong off_zsu_d(void *reg, intptr_t reg_ofs)
6510 {
6511     return (uint32_t)*(uint64_t *)(reg + reg_ofs);
6512 }
6513 
6514 static target_ulong off_zss_d(void *reg, intptr_t reg_ofs)
6515 {
6516     return (int32_t)*(uint64_t *)(reg + reg_ofs);
6517 }
6518 
6519 static target_ulong off_zd_d(void *reg, intptr_t reg_ofs)
6520 {
6521     return *(uint64_t *)(reg + reg_ofs);
6522 }
6523 
6524 static inline QEMU_ALWAYS_INLINE
6525 void sve_ld1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
6526                target_ulong base, uint32_t desc, uintptr_t retaddr,
6527                uint32_t mtedesc, int esize, int msize,
6528                zreg_off_fn *off_fn,
6529                sve_ldst1_host_fn *host_fn,
6530                sve_ldst1_tlb_fn *tlb_fn)
6531 {
6532     const int mmu_idx = arm_env_mmu_index(env);
6533     const intptr_t reg_max = simd_oprsz(desc);
6534     const int scale = simd_data(desc);
6535     ARMVectorReg scratch;
6536     intptr_t reg_off;
6537     SVEHostPage info, info2;
6538 
6539     memset(&scratch, 0, reg_max);
6540     reg_off = 0;
6541     do {
6542         uint64_t pg = vg[reg_off >> 6];
6543         do {
6544             if (likely(pg & 1)) {
6545                 target_ulong addr = base + (off_fn(vm, reg_off) << scale);
6546                 target_ulong in_page = -(addr | TARGET_PAGE_MASK);
6547 
6548                 sve_probe_page(&info, false, env, addr, 0, MMU_DATA_LOAD,
6549                                mmu_idx, retaddr);
6550 
6551                 if (likely(in_page >= msize)) {
6552                     if (unlikely(info.flags & TLB_WATCHPOINT)) {
6553                         cpu_check_watchpoint(env_cpu(env), addr, msize,
6554                                              info.attrs, BP_MEM_READ, retaddr);
6555                     }
6556                     if (mtedesc && info.tagged) {
6557                         mte_check(env, mtedesc, addr, retaddr);
6558                     }
6559                     if (unlikely(info.flags & TLB_MMIO)) {
6560                         tlb_fn(env, &scratch, reg_off, addr, retaddr);
6561                     } else {
6562                         host_fn(&scratch, reg_off, info.host);
6563                     }
6564                 } else {
6565                     /* Element crosses the page boundary. */
6566                     sve_probe_page(&info2, false, env, addr + in_page, 0,
6567                                    MMU_DATA_LOAD, mmu_idx, retaddr);
6568                     if (unlikely((info.flags | info2.flags) & TLB_WATCHPOINT)) {
6569                         cpu_check_watchpoint(env_cpu(env), addr,
6570                                              msize, info.attrs,
6571                                              BP_MEM_READ, retaddr);
6572                     }
6573                     if (mtedesc && info.tagged) {
6574                         mte_check(env, mtedesc, addr, retaddr);
6575                     }
6576                     tlb_fn(env, &scratch, reg_off, addr, retaddr);
6577                 }
6578             }
6579             reg_off += esize;
6580             pg >>= esize;
6581         } while (reg_off & 63);
6582     } while (reg_off < reg_max);
6583 
6584     /* Wait until all exceptions have been raised to write back.  */
6585     memcpy(vd, &scratch, reg_max);
6586 }
6587 
6588 static inline QEMU_ALWAYS_INLINE
6589 void sve_ld1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
6590                    target_ulong base, uint32_t desc, uintptr_t retaddr,
6591                    int esize, int msize, zreg_off_fn *off_fn,
6592                    sve_ldst1_host_fn *host_fn,
6593                    sve_ldst1_tlb_fn *tlb_fn)
6594 {
6595     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6596     /* Remove mtedesc from the normal sve descriptor. */
6597     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6598 
6599     /*
6600      * ??? TODO: For the 32-bit offset extractions, base + ofs cannot
6601      * offset base entirely over the address space hole to change the
6602      * pointer tag, or change the bit55 selector.  So we could here
6603      * examine TBI + TCMA like we do for sve_ldN_r_mte().
6604      */
6605     sve_ld1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc,
6606               esize, msize, off_fn, host_fn, tlb_fn);
6607 }
6608 
6609 #define DO_LD1_ZPZ_S(MEM, OFS, MSZ) \
6610 void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg,       \
6611                                  void *vm, target_ulong base, uint32_t desc) \
6612 {                                                                            \
6613     sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 4, 1 << MSZ,          \
6614               off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb);       \
6615 }                                                                            \
6616 void HELPER(sve_ld##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \
6617      void *vm, target_ulong base, uint32_t desc)                             \
6618 {                                                                            \
6619     sve_ld1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ,         \
6620                   off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb);   \
6621 }
6622 
6623 #define DO_LD1_ZPZ_D(MEM, OFS, MSZ) \
6624 void HELPER(sve_ld##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg,       \
6625                                  void *vm, target_ulong base, uint32_t desc) \
6626 {                                                                            \
6627     sve_ld1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 8, 1 << MSZ,          \
6628               off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb);       \
6629 }                                                                            \
6630 void HELPER(sve_ld##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \
6631     void *vm, target_ulong base, uint32_t desc)                              \
6632 {                                                                            \
6633     sve_ld1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ,         \
6634                   off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb);   \
6635 }
6636 
6637 DO_LD1_ZPZ_S(bsu, zsu, MO_8)
6638 DO_LD1_ZPZ_S(bsu, zss, MO_8)
6639 DO_LD1_ZPZ_D(bdu, zsu, MO_8)
6640 DO_LD1_ZPZ_D(bdu, zss, MO_8)
6641 DO_LD1_ZPZ_D(bdu, zd, MO_8)
6642 
6643 DO_LD1_ZPZ_S(bss, zsu, MO_8)
6644 DO_LD1_ZPZ_S(bss, zss, MO_8)
6645 DO_LD1_ZPZ_D(bds, zsu, MO_8)
6646 DO_LD1_ZPZ_D(bds, zss, MO_8)
6647 DO_LD1_ZPZ_D(bds, zd, MO_8)
6648 
6649 DO_LD1_ZPZ_S(hsu_le, zsu, MO_16)
6650 DO_LD1_ZPZ_S(hsu_le, zss, MO_16)
6651 DO_LD1_ZPZ_D(hdu_le, zsu, MO_16)
6652 DO_LD1_ZPZ_D(hdu_le, zss, MO_16)
6653 DO_LD1_ZPZ_D(hdu_le, zd, MO_16)
6654 
6655 DO_LD1_ZPZ_S(hsu_be, zsu, MO_16)
6656 DO_LD1_ZPZ_S(hsu_be, zss, MO_16)
6657 DO_LD1_ZPZ_D(hdu_be, zsu, MO_16)
6658 DO_LD1_ZPZ_D(hdu_be, zss, MO_16)
6659 DO_LD1_ZPZ_D(hdu_be, zd, MO_16)
6660 
6661 DO_LD1_ZPZ_S(hss_le, zsu, MO_16)
6662 DO_LD1_ZPZ_S(hss_le, zss, MO_16)
6663 DO_LD1_ZPZ_D(hds_le, zsu, MO_16)
6664 DO_LD1_ZPZ_D(hds_le, zss, MO_16)
6665 DO_LD1_ZPZ_D(hds_le, zd, MO_16)
6666 
6667 DO_LD1_ZPZ_S(hss_be, zsu, MO_16)
6668 DO_LD1_ZPZ_S(hss_be, zss, MO_16)
6669 DO_LD1_ZPZ_D(hds_be, zsu, MO_16)
6670 DO_LD1_ZPZ_D(hds_be, zss, MO_16)
6671 DO_LD1_ZPZ_D(hds_be, zd, MO_16)
6672 
6673 DO_LD1_ZPZ_S(ss_le, zsu, MO_32)
6674 DO_LD1_ZPZ_S(ss_le, zss, MO_32)
6675 DO_LD1_ZPZ_D(sdu_le, zsu, MO_32)
6676 DO_LD1_ZPZ_D(sdu_le, zss, MO_32)
6677 DO_LD1_ZPZ_D(sdu_le, zd, MO_32)
6678 
6679 DO_LD1_ZPZ_S(ss_be, zsu, MO_32)
6680 DO_LD1_ZPZ_S(ss_be, zss, MO_32)
6681 DO_LD1_ZPZ_D(sdu_be, zsu, MO_32)
6682 DO_LD1_ZPZ_D(sdu_be, zss, MO_32)
6683 DO_LD1_ZPZ_D(sdu_be, zd, MO_32)
6684 
6685 DO_LD1_ZPZ_D(sds_le, zsu, MO_32)
6686 DO_LD1_ZPZ_D(sds_le, zss, MO_32)
6687 DO_LD1_ZPZ_D(sds_le, zd, MO_32)
6688 
6689 DO_LD1_ZPZ_D(sds_be, zsu, MO_32)
6690 DO_LD1_ZPZ_D(sds_be, zss, MO_32)
6691 DO_LD1_ZPZ_D(sds_be, zd, MO_32)
6692 
6693 DO_LD1_ZPZ_D(dd_le, zsu, MO_64)
6694 DO_LD1_ZPZ_D(dd_le, zss, MO_64)
6695 DO_LD1_ZPZ_D(dd_le, zd, MO_64)
6696 
6697 DO_LD1_ZPZ_D(dd_be, zsu, MO_64)
6698 DO_LD1_ZPZ_D(dd_be, zss, MO_64)
6699 DO_LD1_ZPZ_D(dd_be, zd, MO_64)
6700 
6701 #undef DO_LD1_ZPZ_S
6702 #undef DO_LD1_ZPZ_D
6703 
6704 /* First fault loads with a vector index.  */
6705 
6706 /*
6707  * Common helpers for all gather first-faulting loads.
6708  */
6709 
6710 static inline QEMU_ALWAYS_INLINE
6711 void sve_ldff1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
6712                  target_ulong base, uint32_t desc, uintptr_t retaddr,
6713                  uint32_t mtedesc, const int esz, const int msz,
6714                  zreg_off_fn *off_fn,
6715                  sve_ldst1_host_fn *host_fn,
6716                  sve_ldst1_tlb_fn *tlb_fn)
6717 {
6718     const int mmu_idx = arm_env_mmu_index(env);
6719     const intptr_t reg_max = simd_oprsz(desc);
6720     const int scale = simd_data(desc);
6721     const int esize = 1 << esz;
6722     const int msize = 1 << msz;
6723     intptr_t reg_off;
6724     SVEHostPage info;
6725     target_ulong addr, in_page;
6726     ARMVectorReg scratch;
6727 
6728     /* Skip to the first true predicate.  */
6729     reg_off = find_next_active(vg, 0, reg_max, esz);
6730     if (unlikely(reg_off >= reg_max)) {
6731         /* The entire predicate was false; no load occurs.  */
6732         memset(vd, 0, reg_max);
6733         return;
6734     }
6735 
6736     /* Protect against overlap between vd and vm. */
6737     if (unlikely(vd == vm)) {
6738         vm = memcpy(&scratch, vm, reg_max);
6739     }
6740 
6741     /*
6742      * Probe the first element, allowing faults.
6743      */
6744     addr = base + (off_fn(vm, reg_off) << scale);
6745     if (mtedesc) {
6746         mte_check(env, mtedesc, addr, retaddr);
6747     }
6748     tlb_fn(env, vd, reg_off, addr, retaddr);
6749 
6750     /* After any fault, zero the other elements. */
6751     swap_memzero(vd, reg_off);
6752     reg_off += esize;
6753     swap_memzero(vd + reg_off, reg_max - reg_off);
6754 
6755     /*
6756      * Probe the remaining elements, not allowing faults.
6757      */
6758     while (reg_off < reg_max) {
6759         uint64_t pg = vg[reg_off >> 6];
6760         do {
6761             if (likely((pg >> (reg_off & 63)) & 1)) {
6762                 addr = base + (off_fn(vm, reg_off) << scale);
6763                 in_page = -(addr | TARGET_PAGE_MASK);
6764 
6765                 if (unlikely(in_page < msize)) {
6766                     /* Stop if the element crosses a page boundary. */
6767                     goto fault;
6768                 }
6769 
6770                 sve_probe_page(&info, true, env, addr, 0, MMU_DATA_LOAD,
6771                                mmu_idx, retaddr);
6772                 if (unlikely(info.flags & (TLB_INVALID_MASK | TLB_MMIO))) {
6773                     goto fault;
6774                 }
6775                 if (unlikely(info.flags & TLB_WATCHPOINT) &&
6776                     (cpu_watchpoint_address_matches
6777                      (env_cpu(env), addr, msize) & BP_MEM_READ)) {
6778                     goto fault;
6779                 }
6780                 if (mtedesc && info.tagged && !mte_probe(env, mtedesc, addr)) {
6781                     goto fault;
6782                 }
6783 
6784                 host_fn(vd, reg_off, info.host);
6785             }
6786             reg_off += esize;
6787         } while (reg_off & 63);
6788     }
6789     return;
6790 
6791  fault:
6792     record_fault(env, reg_off, reg_max);
6793 }
6794 
6795 static inline QEMU_ALWAYS_INLINE
6796 void sve_ldff1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
6797                      target_ulong base, uint32_t desc, uintptr_t retaddr,
6798                      const int esz, const int msz,
6799                      zreg_off_fn *off_fn,
6800                      sve_ldst1_host_fn *host_fn,
6801                      sve_ldst1_tlb_fn *tlb_fn)
6802 {
6803     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6804     /* Remove mtedesc from the normal sve descriptor. */
6805     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
6806 
6807     /*
6808      * ??? TODO: For the 32-bit offset extractions, base + ofs cannot
6809      * offset base entirely over the address space hole to change the
6810      * pointer tag, or change the bit55 selector.  So we could here
6811      * examine TBI + TCMA like we do for sve_ldN_r_mte().
6812      */
6813     sve_ldff1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc,
6814                 esz, msz, off_fn, host_fn, tlb_fn);
6815 }
6816 
6817 #define DO_LDFF1_ZPZ_S(MEM, OFS, MSZ)                                   \
6818 void HELPER(sve_ldff##MEM##_##OFS)                                      \
6819     (CPUARMState *env, void *vd, void *vg,                              \
6820      void *vm, target_ulong base, uint32_t desc)                        \
6821 {                                                                       \
6822     sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), 0, MO_32, MSZ,    \
6823                 off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \
6824 }                                                                       \
6825 void HELPER(sve_ldff##MEM##_##OFS##_mte)                                \
6826     (CPUARMState *env, void *vd, void *vg,                              \
6827      void *vm, target_ulong base, uint32_t desc)                        \
6828 {                                                                       \
6829     sve_ldff1_z_mte(env, vd, vg, vm, base, desc, GETPC(), MO_32, MSZ,   \
6830                     off_##OFS##_s, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \
6831 }
6832 
6833 #define DO_LDFF1_ZPZ_D(MEM, OFS, MSZ)                                   \
6834 void HELPER(sve_ldff##MEM##_##OFS)                                      \
6835     (CPUARMState *env, void *vd, void *vg,                              \
6836      void *vm, target_ulong base, uint32_t desc)                        \
6837 {                                                                       \
6838     sve_ldff1_z(env, vd, vg, vm, base, desc, GETPC(), 0, MO_64, MSZ,    \
6839                 off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \
6840 }                                                                       \
6841 void HELPER(sve_ldff##MEM##_##OFS##_mte)                                \
6842     (CPUARMState *env, void *vd, void *vg,                              \
6843      void *vm, target_ulong base, uint32_t desc)                        \
6844 {                                                                       \
6845     sve_ldff1_z_mte(env, vd, vg, vm, base, desc, GETPC(), MO_64, MSZ,   \
6846                     off_##OFS##_d, sve_ld1##MEM##_host, sve_ld1##MEM##_tlb); \
6847 }
6848 
6849 DO_LDFF1_ZPZ_S(bsu, zsu, MO_8)
6850 DO_LDFF1_ZPZ_S(bsu, zss, MO_8)
6851 DO_LDFF1_ZPZ_D(bdu, zsu, MO_8)
6852 DO_LDFF1_ZPZ_D(bdu, zss, MO_8)
6853 DO_LDFF1_ZPZ_D(bdu, zd, MO_8)
6854 
6855 DO_LDFF1_ZPZ_S(bss, zsu, MO_8)
6856 DO_LDFF1_ZPZ_S(bss, zss, MO_8)
6857 DO_LDFF1_ZPZ_D(bds, zsu, MO_8)
6858 DO_LDFF1_ZPZ_D(bds, zss, MO_8)
6859 DO_LDFF1_ZPZ_D(bds, zd, MO_8)
6860 
6861 DO_LDFF1_ZPZ_S(hsu_le, zsu, MO_16)
6862 DO_LDFF1_ZPZ_S(hsu_le, zss, MO_16)
6863 DO_LDFF1_ZPZ_D(hdu_le, zsu, MO_16)
6864 DO_LDFF1_ZPZ_D(hdu_le, zss, MO_16)
6865 DO_LDFF1_ZPZ_D(hdu_le, zd, MO_16)
6866 
6867 DO_LDFF1_ZPZ_S(hsu_be, zsu, MO_16)
6868 DO_LDFF1_ZPZ_S(hsu_be, zss, MO_16)
6869 DO_LDFF1_ZPZ_D(hdu_be, zsu, MO_16)
6870 DO_LDFF1_ZPZ_D(hdu_be, zss, MO_16)
6871 DO_LDFF1_ZPZ_D(hdu_be, zd, MO_16)
6872 
6873 DO_LDFF1_ZPZ_S(hss_le, zsu, MO_16)
6874 DO_LDFF1_ZPZ_S(hss_le, zss, MO_16)
6875 DO_LDFF1_ZPZ_D(hds_le, zsu, MO_16)
6876 DO_LDFF1_ZPZ_D(hds_le, zss, MO_16)
6877 DO_LDFF1_ZPZ_D(hds_le, zd, MO_16)
6878 
6879 DO_LDFF1_ZPZ_S(hss_be, zsu, MO_16)
6880 DO_LDFF1_ZPZ_S(hss_be, zss, MO_16)
6881 DO_LDFF1_ZPZ_D(hds_be, zsu, MO_16)
6882 DO_LDFF1_ZPZ_D(hds_be, zss, MO_16)
6883 DO_LDFF1_ZPZ_D(hds_be, zd, MO_16)
6884 
6885 DO_LDFF1_ZPZ_S(ss_le,  zsu, MO_32)
6886 DO_LDFF1_ZPZ_S(ss_le,  zss, MO_32)
6887 DO_LDFF1_ZPZ_D(sdu_le, zsu, MO_32)
6888 DO_LDFF1_ZPZ_D(sdu_le, zss, MO_32)
6889 DO_LDFF1_ZPZ_D(sdu_le, zd, MO_32)
6890 
6891 DO_LDFF1_ZPZ_S(ss_be,  zsu, MO_32)
6892 DO_LDFF1_ZPZ_S(ss_be,  zss, MO_32)
6893 DO_LDFF1_ZPZ_D(sdu_be, zsu, MO_32)
6894 DO_LDFF1_ZPZ_D(sdu_be, zss, MO_32)
6895 DO_LDFF1_ZPZ_D(sdu_be, zd, MO_32)
6896 
6897 DO_LDFF1_ZPZ_D(sds_le, zsu, MO_32)
6898 DO_LDFF1_ZPZ_D(sds_le, zss, MO_32)
6899 DO_LDFF1_ZPZ_D(sds_le, zd, MO_32)
6900 
6901 DO_LDFF1_ZPZ_D(sds_be, zsu, MO_32)
6902 DO_LDFF1_ZPZ_D(sds_be, zss, MO_32)
6903 DO_LDFF1_ZPZ_D(sds_be, zd, MO_32)
6904 
6905 DO_LDFF1_ZPZ_D(dd_le, zsu, MO_64)
6906 DO_LDFF1_ZPZ_D(dd_le, zss, MO_64)
6907 DO_LDFF1_ZPZ_D(dd_le, zd, MO_64)
6908 
6909 DO_LDFF1_ZPZ_D(dd_be, zsu, MO_64)
6910 DO_LDFF1_ZPZ_D(dd_be, zss, MO_64)
6911 DO_LDFF1_ZPZ_D(dd_be, zd, MO_64)
6912 
6913 /* Stores with a vector index.  */
6914 
6915 static inline QEMU_ALWAYS_INLINE
6916 void sve_st1_z(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
6917                target_ulong base, uint32_t desc, uintptr_t retaddr,
6918                uint32_t mtedesc, int esize, int msize,
6919                zreg_off_fn *off_fn,
6920                sve_ldst1_host_fn *host_fn,
6921                sve_ldst1_tlb_fn *tlb_fn)
6922 {
6923     const int mmu_idx = arm_env_mmu_index(env);
6924     const intptr_t reg_max = simd_oprsz(desc);
6925     const int scale = simd_data(desc);
6926     void *host[ARM_MAX_VQ * 4];
6927     intptr_t reg_off, i;
6928     SVEHostPage info, info2;
6929 
6930     /*
6931      * Probe all of the elements for host addresses and flags.
6932      */
6933     i = reg_off = 0;
6934     do {
6935         uint64_t pg = vg[reg_off >> 6];
6936         do {
6937             target_ulong addr = base + (off_fn(vm, reg_off) << scale);
6938             target_ulong in_page = -(addr | TARGET_PAGE_MASK);
6939 
6940             host[i] = NULL;
6941             if (likely((pg >> (reg_off & 63)) & 1)) {
6942                 if (likely(in_page >= msize)) {
6943                     sve_probe_page(&info, false, env, addr, 0, MMU_DATA_STORE,
6944                                    mmu_idx, retaddr);
6945                     if (!(info.flags & TLB_MMIO)) {
6946                         host[i] = info.host;
6947                     }
6948                 } else {
6949                     /*
6950                      * Element crosses the page boundary.
6951                      * Probe both pages, but do not record the host address,
6952                      * so that we use the slow path.
6953                      */
6954                     sve_probe_page(&info, false, env, addr, 0,
6955                                    MMU_DATA_STORE, mmu_idx, retaddr);
6956                     sve_probe_page(&info2, false, env, addr + in_page, 0,
6957                                    MMU_DATA_STORE, mmu_idx, retaddr);
6958                     info.flags |= info2.flags;
6959                 }
6960 
6961                 if (unlikely(info.flags & TLB_WATCHPOINT)) {
6962                     cpu_check_watchpoint(env_cpu(env), addr, msize,
6963                                          info.attrs, BP_MEM_WRITE, retaddr);
6964                 }
6965 
6966                 if (mtedesc && info.tagged) {
6967                     mte_check(env, mtedesc, addr, retaddr);
6968                 }
6969             }
6970             i += 1;
6971             reg_off += esize;
6972         } while (reg_off & 63);
6973     } while (reg_off < reg_max);
6974 
6975     /*
6976      * Now that we have recognized all exceptions except SyncExternal
6977      * (from TLB_MMIO), which we cannot avoid, perform all of the stores.
6978      *
6979      * Note for the common case of an element in RAM, not crossing a page
6980      * boundary, we have stored the host address in host[].  This doubles
6981      * as a first-level check against the predicate, since only enabled
6982      * elements have non-null host addresses.
6983      */
6984     i = reg_off = 0;
6985     do {
6986         void *h = host[i];
6987         if (likely(h != NULL)) {
6988             host_fn(vd, reg_off, h);
6989         } else if ((vg[reg_off >> 6] >> (reg_off & 63)) & 1) {
6990             target_ulong addr = base + (off_fn(vm, reg_off) << scale);
6991             tlb_fn(env, vd, reg_off, addr, retaddr);
6992         }
6993         i += 1;
6994         reg_off += esize;
6995     } while (reg_off < reg_max);
6996 }
6997 
6998 static inline QEMU_ALWAYS_INLINE
6999 void sve_st1_z_mte(CPUARMState *env, void *vd, uint64_t *vg, void *vm,
7000                    target_ulong base, uint32_t desc, uintptr_t retaddr,
7001                    int esize, int msize, zreg_off_fn *off_fn,
7002                    sve_ldst1_host_fn *host_fn,
7003                    sve_ldst1_tlb_fn *tlb_fn)
7004 {
7005     uint32_t mtedesc = desc >> (SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
7006     /* Remove mtedesc from the normal sve descriptor. */
7007     desc = extract32(desc, 0, SIMD_DATA_SHIFT + SVE_MTEDESC_SHIFT);
7008 
7009     /*
7010      * ??? TODO: For the 32-bit offset extractions, base + ofs cannot
7011      * offset base entirely over the address space hole to change the
7012      * pointer tag, or change the bit55 selector.  So we could here
7013      * examine TBI + TCMA like we do for sve_ldN_r_mte().
7014      */
7015     sve_st1_z(env, vd, vg, vm, base, desc, retaddr, mtedesc,
7016               esize, msize, off_fn, host_fn, tlb_fn);
7017 }
7018 
7019 #define DO_ST1_ZPZ_S(MEM, OFS, MSZ)                                     \
7020 void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg,  \
7021                                  void *vm, target_ulong base, uint32_t desc) \
7022 {                                                                       \
7023     sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 4, 1 << MSZ,     \
7024               off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb);  \
7025 }                                                                       \
7026 void HELPER(sve_st##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \
7027     void *vm, target_ulong base, uint32_t desc)                         \
7028 {                                                                       \
7029     sve_st1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 4, 1 << MSZ,    \
7030                   off_##OFS##_s, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \
7031 }
7032 
7033 #define DO_ST1_ZPZ_D(MEM, OFS, MSZ)                                     \
7034 void HELPER(sve_st##MEM##_##OFS)(CPUARMState *env, void *vd, void *vg,  \
7035                                  void *vm, target_ulong base, uint32_t desc) \
7036 {                                                                       \
7037     sve_st1_z(env, vd, vg, vm, base, desc, GETPC(), 0, 8, 1 << MSZ,     \
7038               off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb);  \
7039 }                                                                       \
7040 void HELPER(sve_st##MEM##_##OFS##_mte)(CPUARMState *env, void *vd, void *vg, \
7041     void *vm, target_ulong base, uint32_t desc)                         \
7042 {                                                                       \
7043     sve_st1_z_mte(env, vd, vg, vm, base, desc, GETPC(), 8, 1 << MSZ,    \
7044                   off_##OFS##_d, sve_st1##MEM##_host, sve_st1##MEM##_tlb); \
7045 }
7046 
7047 DO_ST1_ZPZ_S(bs, zsu, MO_8)
7048 DO_ST1_ZPZ_S(hs_le, zsu, MO_16)
7049 DO_ST1_ZPZ_S(hs_be, zsu, MO_16)
7050 DO_ST1_ZPZ_S(ss_le, zsu, MO_32)
7051 DO_ST1_ZPZ_S(ss_be, zsu, MO_32)
7052 
7053 DO_ST1_ZPZ_S(bs, zss, MO_8)
7054 DO_ST1_ZPZ_S(hs_le, zss, MO_16)
7055 DO_ST1_ZPZ_S(hs_be, zss, MO_16)
7056 DO_ST1_ZPZ_S(ss_le, zss, MO_32)
7057 DO_ST1_ZPZ_S(ss_be, zss, MO_32)
7058 
7059 DO_ST1_ZPZ_D(bd, zsu, MO_8)
7060 DO_ST1_ZPZ_D(hd_le, zsu, MO_16)
7061 DO_ST1_ZPZ_D(hd_be, zsu, MO_16)
7062 DO_ST1_ZPZ_D(sd_le, zsu, MO_32)
7063 DO_ST1_ZPZ_D(sd_be, zsu, MO_32)
7064 DO_ST1_ZPZ_D(dd_le, zsu, MO_64)
7065 DO_ST1_ZPZ_D(dd_be, zsu, MO_64)
7066 
7067 DO_ST1_ZPZ_D(bd, zss, MO_8)
7068 DO_ST1_ZPZ_D(hd_le, zss, MO_16)
7069 DO_ST1_ZPZ_D(hd_be, zss, MO_16)
7070 DO_ST1_ZPZ_D(sd_le, zss, MO_32)
7071 DO_ST1_ZPZ_D(sd_be, zss, MO_32)
7072 DO_ST1_ZPZ_D(dd_le, zss, MO_64)
7073 DO_ST1_ZPZ_D(dd_be, zss, MO_64)
7074 
7075 DO_ST1_ZPZ_D(bd, zd, MO_8)
7076 DO_ST1_ZPZ_D(hd_le, zd, MO_16)
7077 DO_ST1_ZPZ_D(hd_be, zd, MO_16)
7078 DO_ST1_ZPZ_D(sd_le, zd, MO_32)
7079 DO_ST1_ZPZ_D(sd_be, zd, MO_32)
7080 DO_ST1_ZPZ_D(dd_le, zd, MO_64)
7081 DO_ST1_ZPZ_D(dd_be, zd, MO_64)
7082 
7083 #undef DO_ST1_ZPZ_S
7084 #undef DO_ST1_ZPZ_D
7085 
7086 void HELPER(sve2_eor3)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
7087 {
7088     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7089     uint64_t *d = vd, *n = vn, *m = vm, *k = vk;
7090 
7091     for (i = 0; i < opr_sz; ++i) {
7092         d[i] = n[i] ^ m[i] ^ k[i];
7093     }
7094 }
7095 
7096 void HELPER(sve2_bcax)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
7097 {
7098     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7099     uint64_t *d = vd, *n = vn, *m = vm, *k = vk;
7100 
7101     for (i = 0; i < opr_sz; ++i) {
7102         d[i] = n[i] ^ (m[i] & ~k[i]);
7103     }
7104 }
7105 
7106 void HELPER(sve2_bsl1n)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
7107 {
7108     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7109     uint64_t *d = vd, *n = vn, *m = vm, *k = vk;
7110 
7111     for (i = 0; i < opr_sz; ++i) {
7112         d[i] = (~n[i] & k[i]) | (m[i] & ~k[i]);
7113     }
7114 }
7115 
7116 void HELPER(sve2_bsl2n)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
7117 {
7118     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7119     uint64_t *d = vd, *n = vn, *m = vm, *k = vk;
7120 
7121     for (i = 0; i < opr_sz; ++i) {
7122         d[i] = (n[i] & k[i]) | (~m[i] & ~k[i]);
7123     }
7124 }
7125 
7126 void HELPER(sve2_nbsl)(void *vd, void *vn, void *vm, void *vk, uint32_t desc)
7127 {
7128     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7129     uint64_t *d = vd, *n = vn, *m = vm, *k = vk;
7130 
7131     for (i = 0; i < opr_sz; ++i) {
7132         d[i] = ~((n[i] & k[i]) | (m[i] & ~k[i]));
7133     }
7134 }
7135 
7136 /*
7137  * Returns true if m0 or m1 contains the low uint8_t/uint16_t in n.
7138  * See hasless(v,1) from
7139  *   https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
7140  */
7141 static inline bool do_match2(uint64_t n, uint64_t m0, uint64_t m1, int esz)
7142 {
7143     int bits = 8 << esz;
7144     uint64_t ones = dup_const(esz, 1);
7145     uint64_t signs = ones << (bits - 1);
7146     uint64_t cmp0, cmp1;
7147 
7148     cmp1 = dup_const(esz, n);
7149     cmp0 = cmp1 ^ m0;
7150     cmp1 = cmp1 ^ m1;
7151     cmp0 = (cmp0 - ones) & ~cmp0;
7152     cmp1 = (cmp1 - ones) & ~cmp1;
7153     return (cmp0 | cmp1) & signs;
7154 }
7155 
7156 static inline uint32_t do_match(void *vd, void *vn, void *vm, void *vg,
7157                                 uint32_t desc, int esz, bool nmatch)
7158 {
7159     uint16_t esz_mask = pred_esz_masks[esz];
7160     intptr_t opr_sz = simd_oprsz(desc);
7161     uint32_t flags = PREDTEST_INIT;
7162     intptr_t i, j, k;
7163 
7164     for (i = 0; i < opr_sz; i += 16) {
7165         uint64_t m0 = *(uint64_t *)(vm + i);
7166         uint64_t m1 = *(uint64_t *)(vm + i + 8);
7167         uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)) & esz_mask;
7168         uint16_t out = 0;
7169 
7170         for (j = 0; j < 16; j += 8) {
7171             uint64_t n = *(uint64_t *)(vn + i + j);
7172 
7173             for (k = 0; k < 8; k += 1 << esz) {
7174                 if (pg & (1 << (j + k))) {
7175                     bool o = do_match2(n >> (k * 8), m0, m1, esz);
7176                     out |= (o ^ nmatch) << (j + k);
7177                 }
7178             }
7179         }
7180         *(uint16_t *)(vd + H1_2(i >> 3)) = out;
7181         flags = iter_predtest_fwd(out, pg, flags);
7182     }
7183     return flags;
7184 }
7185 
7186 #define DO_PPZZ_MATCH(NAME, ESZ, INV)                                         \
7187 uint32_t HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)  \
7188 {                                                                             \
7189     return do_match(vd, vn, vm, vg, desc, ESZ, INV);                          \
7190 }
7191 
7192 DO_PPZZ_MATCH(sve2_match_ppzz_b, MO_8, false)
7193 DO_PPZZ_MATCH(sve2_match_ppzz_h, MO_16, false)
7194 
7195 DO_PPZZ_MATCH(sve2_nmatch_ppzz_b, MO_8, true)
7196 DO_PPZZ_MATCH(sve2_nmatch_ppzz_h, MO_16, true)
7197 
7198 #undef DO_PPZZ_MATCH
7199 
7200 void HELPER(sve2_histcnt_s)(void *vd, void *vn, void *vm, void *vg,
7201                             uint32_t desc)
7202 {
7203     ARMVectorReg scratch;
7204     intptr_t i, j;
7205     intptr_t opr_sz = simd_oprsz(desc);
7206     uint32_t *d = vd, *n = vn, *m = vm;
7207     uint8_t *pg = vg;
7208 
7209     if (d == n) {
7210         n = memcpy(&scratch, n, opr_sz);
7211         if (d == m) {
7212             m = n;
7213         }
7214     } else if (d == m) {
7215         m = memcpy(&scratch, m, opr_sz);
7216     }
7217 
7218     for (i = 0; i < opr_sz; i += 4) {
7219         uint64_t count = 0;
7220         uint8_t pred;
7221 
7222         pred = pg[H1(i >> 3)] >> (i & 7);
7223         if (pred & 1) {
7224             uint32_t nn = n[H4(i >> 2)];
7225 
7226             for (j = 0; j <= i; j += 4) {
7227                 pred = pg[H1(j >> 3)] >> (j & 7);
7228                 if ((pred & 1) && nn == m[H4(j >> 2)]) {
7229                     ++count;
7230                 }
7231             }
7232         }
7233         d[H4(i >> 2)] = count;
7234     }
7235 }
7236 
7237 void HELPER(sve2_histcnt_d)(void *vd, void *vn, void *vm, void *vg,
7238                             uint32_t desc)
7239 {
7240     ARMVectorReg scratch;
7241     intptr_t i, j;
7242     intptr_t opr_sz = simd_oprsz(desc);
7243     uint64_t *d = vd, *n = vn, *m = vm;
7244     uint8_t *pg = vg;
7245 
7246     if (d == n) {
7247         n = memcpy(&scratch, n, opr_sz);
7248         if (d == m) {
7249             m = n;
7250         }
7251     } else if (d == m) {
7252         m = memcpy(&scratch, m, opr_sz);
7253     }
7254 
7255     for (i = 0; i < opr_sz / 8; ++i) {
7256         uint64_t count = 0;
7257         if (pg[H1(i)] & 1) {
7258             uint64_t nn = n[i];
7259             for (j = 0; j <= i; ++j) {
7260                 if ((pg[H1(j)] & 1) && nn == m[j]) {
7261                     ++count;
7262                 }
7263             }
7264         }
7265         d[i] = count;
7266     }
7267 }
7268 
7269 /*
7270  * Returns the number of bytes in m0 and m1 that match n.
7271  * Unlike do_match2 we don't just need true/false, we need an exact count.
7272  * This requires two extra logical operations.
7273  */
7274 static inline uint64_t do_histseg_cnt(uint8_t n, uint64_t m0, uint64_t m1)
7275 {
7276     const uint64_t mask = dup_const(MO_8, 0x7f);
7277     uint64_t cmp0, cmp1;
7278 
7279     cmp1 = dup_const(MO_8, n);
7280     cmp0 = cmp1 ^ m0;
7281     cmp1 = cmp1 ^ m1;
7282 
7283     /*
7284      * 1: clear msb of each byte to avoid carry to next byte (& mask)
7285      * 2: carry in to msb if byte != 0 (+ mask)
7286      * 3: set msb if cmp has msb set (| cmp)
7287      * 4: set ~msb to ignore them (| mask)
7288      * We now have 0xff for byte != 0 or 0x7f for byte == 0.
7289      * 5: invert, resulting in 0x80 if and only if byte == 0.
7290      */
7291     cmp0 = ~(((cmp0 & mask) + mask) | cmp0 | mask);
7292     cmp1 = ~(((cmp1 & mask) + mask) | cmp1 | mask);
7293 
7294     /*
7295      * Combine the two compares in a way that the bits do
7296      * not overlap, and so preserves the count of set bits.
7297      * If the host has an efficient instruction for ctpop,
7298      * then ctpop(x) + ctpop(y) has the same number of
7299      * operations as ctpop(x | (y >> 1)).  If the host does
7300      * not have an efficient ctpop, then we only want to
7301      * use it once.
7302      */
7303     return ctpop64(cmp0 | (cmp1 >> 1));
7304 }
7305 
7306 void HELPER(sve2_histseg)(void *vd, void *vn, void *vm, uint32_t desc)
7307 {
7308     intptr_t i, j;
7309     intptr_t opr_sz = simd_oprsz(desc);
7310 
7311     for (i = 0; i < opr_sz; i += 16) {
7312         uint64_t n0 = *(uint64_t *)(vn + i);
7313         uint64_t m0 = *(uint64_t *)(vm + i);
7314         uint64_t n1 = *(uint64_t *)(vn + i + 8);
7315         uint64_t m1 = *(uint64_t *)(vm + i + 8);
7316         uint64_t out0 = 0;
7317         uint64_t out1 = 0;
7318 
7319         for (j = 0; j < 64; j += 8) {
7320             uint64_t cnt0 = do_histseg_cnt(n0 >> j, m0, m1);
7321             uint64_t cnt1 = do_histseg_cnt(n1 >> j, m0, m1);
7322             out0 |= cnt0 << j;
7323             out1 |= cnt1 << j;
7324         }
7325 
7326         *(uint64_t *)(vd + i) = out0;
7327         *(uint64_t *)(vd + i + 8) = out1;
7328     }
7329 }
7330 
7331 void HELPER(sve2_xar_b)(void *vd, void *vn, void *vm, uint32_t desc)
7332 {
7333     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7334     int shr = simd_data(desc);
7335     int shl = 8 - shr;
7336     uint64_t mask = dup_const(MO_8, 0xff >> shr);
7337     uint64_t *d = vd, *n = vn, *m = vm;
7338 
7339     for (i = 0; i < opr_sz; ++i) {
7340         uint64_t t = n[i] ^ m[i];
7341         d[i] = ((t >> shr) & mask) | ((t << shl) & ~mask);
7342     }
7343 }
7344 
7345 void HELPER(sve2_xar_h)(void *vd, void *vn, void *vm, uint32_t desc)
7346 {
7347     intptr_t i, opr_sz = simd_oprsz(desc) / 8;
7348     int shr = simd_data(desc);
7349     int shl = 16 - shr;
7350     uint64_t mask = dup_const(MO_16, 0xffff >> shr);
7351     uint64_t *d = vd, *n = vn, *m = vm;
7352 
7353     for (i = 0; i < opr_sz; ++i) {
7354         uint64_t t = n[i] ^ m[i];
7355         d[i] = ((t >> shr) & mask) | ((t << shl) & ~mask);
7356     }
7357 }
7358 
7359 void HELPER(sve2_xar_s)(void *vd, void *vn, void *vm, uint32_t desc)
7360 {
7361     intptr_t i, opr_sz = simd_oprsz(desc) / 4;
7362     int shr = simd_data(desc);
7363     uint32_t *d = vd, *n = vn, *m = vm;
7364 
7365     for (i = 0; i < opr_sz; ++i) {
7366         d[i] = ror32(n[i] ^ m[i], shr);
7367     }
7368 }
7369 
7370 void HELPER(fmmla_s)(void *vd, void *vn, void *vm, void *va,
7371                      void *status, uint32_t desc)
7372 {
7373     intptr_t s, opr_sz = simd_oprsz(desc) / (sizeof(float32) * 4);
7374 
7375     for (s = 0; s < opr_sz; ++s) {
7376         float32 *n = vn + s * sizeof(float32) * 4;
7377         float32 *m = vm + s * sizeof(float32) * 4;
7378         float32 *a = va + s * sizeof(float32) * 4;
7379         float32 *d = vd + s * sizeof(float32) * 4;
7380         float32 n00 = n[H4(0)], n01 = n[H4(1)];
7381         float32 n10 = n[H4(2)], n11 = n[H4(3)];
7382         float32 m00 = m[H4(0)], m01 = m[H4(1)];
7383         float32 m10 = m[H4(2)], m11 = m[H4(3)];
7384         float32 p0, p1;
7385 
7386         /* i = 0, j = 0 */
7387         p0 = float32_mul(n00, m00, status);
7388         p1 = float32_mul(n01, m01, status);
7389         d[H4(0)] = float32_add(a[H4(0)], float32_add(p0, p1, status), status);
7390 
7391         /* i = 0, j = 1 */
7392         p0 = float32_mul(n00, m10, status);
7393         p1 = float32_mul(n01, m11, status);
7394         d[H4(1)] = float32_add(a[H4(1)], float32_add(p0, p1, status), status);
7395 
7396         /* i = 1, j = 0 */
7397         p0 = float32_mul(n10, m00, status);
7398         p1 = float32_mul(n11, m01, status);
7399         d[H4(2)] = float32_add(a[H4(2)], float32_add(p0, p1, status), status);
7400 
7401         /* i = 1, j = 1 */
7402         p0 = float32_mul(n10, m10, status);
7403         p1 = float32_mul(n11, m11, status);
7404         d[H4(3)] = float32_add(a[H4(3)], float32_add(p0, p1, status), status);
7405     }
7406 }
7407 
7408 void HELPER(fmmla_d)(void *vd, void *vn, void *vm, void *va,
7409                      void *status, uint32_t desc)
7410 {
7411     intptr_t s, opr_sz = simd_oprsz(desc) / (sizeof(float64) * 4);
7412 
7413     for (s = 0; s < opr_sz; ++s) {
7414         float64 *n = vn + s * sizeof(float64) * 4;
7415         float64 *m = vm + s * sizeof(float64) * 4;
7416         float64 *a = va + s * sizeof(float64) * 4;
7417         float64 *d = vd + s * sizeof(float64) * 4;
7418         float64 n00 = n[0], n01 = n[1], n10 = n[2], n11 = n[3];
7419         float64 m00 = m[0], m01 = m[1], m10 = m[2], m11 = m[3];
7420         float64 p0, p1;
7421 
7422         /* i = 0, j = 0 */
7423         p0 = float64_mul(n00, m00, status);
7424         p1 = float64_mul(n01, m01, status);
7425         d[0] = float64_add(a[0], float64_add(p0, p1, status), status);
7426 
7427         /* i = 0, j = 1 */
7428         p0 = float64_mul(n00, m10, status);
7429         p1 = float64_mul(n01, m11, status);
7430         d[1] = float64_add(a[1], float64_add(p0, p1, status), status);
7431 
7432         /* i = 1, j = 0 */
7433         p0 = float64_mul(n10, m00, status);
7434         p1 = float64_mul(n11, m01, status);
7435         d[2] = float64_add(a[2], float64_add(p0, p1, status), status);
7436 
7437         /* i = 1, j = 1 */
7438         p0 = float64_mul(n10, m10, status);
7439         p1 = float64_mul(n11, m11, status);
7440         d[3] = float64_add(a[3], float64_add(p0, p1, status), status);
7441     }
7442 }
7443 
7444 #define DO_FCVTNT(NAME, TYPEW, TYPEN, HW, HN, OP)                             \
7445 void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc)  \
7446 {                                                                             \
7447     intptr_t i = simd_oprsz(desc);                                            \
7448     uint64_t *g = vg;                                                         \
7449     do {                                                                      \
7450         uint64_t pg = g[(i - 1) >> 6];                                        \
7451         do {                                                                  \
7452             i -= sizeof(TYPEW);                                               \
7453             if (likely((pg >> (i & 63)) & 1)) {                               \
7454                 TYPEW nn = *(TYPEW *)(vn + HW(i));                            \
7455                 *(TYPEN *)(vd + HN(i + sizeof(TYPEN))) = OP(nn, status);      \
7456             }                                                                 \
7457         } while (i & 63);                                                     \
7458     } while (i != 0);                                                         \
7459 }
7460 
7461 DO_FCVTNT(sve_bfcvtnt,    uint32_t, uint16_t, H1_4, H1_2, float32_to_bfloat16)
7462 DO_FCVTNT(sve2_fcvtnt_sh, uint32_t, uint16_t, H1_4, H1_2, sve_f32_to_f16)
7463 DO_FCVTNT(sve2_fcvtnt_ds, uint64_t, uint32_t, H1_8, H1_4, float64_to_float32)
7464 
7465 #define DO_FCVTLT(NAME, TYPEW, TYPEN, HW, HN, OP)                             \
7466 void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc)  \
7467 {                                                                             \
7468     intptr_t i = simd_oprsz(desc);                                            \
7469     uint64_t *g = vg;                                                         \
7470     do {                                                                      \
7471         uint64_t pg = g[(i - 1) >> 6];                                        \
7472         do {                                                                  \
7473             i -= sizeof(TYPEW);                                               \
7474             if (likely((pg >> (i & 63)) & 1)) {                               \
7475                 TYPEN nn = *(TYPEN *)(vn + HN(i + sizeof(TYPEN)));            \
7476                 *(TYPEW *)(vd + HW(i)) = OP(nn, status);                      \
7477             }                                                                 \
7478         } while (i & 63);                                                     \
7479     } while (i != 0);                                                         \
7480 }
7481 
7482 DO_FCVTLT(sve2_fcvtlt_hs, uint32_t, uint16_t, H1_4, H1_2, sve_f16_to_f32)
7483 DO_FCVTLT(sve2_fcvtlt_sd, uint64_t, uint32_t, H1_8, H1_4, float32_to_float64)
7484 
7485 #undef DO_FCVTLT
7486 #undef DO_FCVTNT
7487