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