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