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