xref: /qemu/tcg/tcg-op-gvec.c (revision c888f7e0)
1 /*
2  * Generic vector operation expansion
3  *
4  * Copyright (c) 2018 Linaro
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 "tcg/tcg.h"
22 #include "tcg/tcg-op.h"
23 #include "tcg/tcg-op-gvec.h"
24 #include "qemu/main-loop.h"
25 #include "tcg/tcg-gvec-desc.h"
26 
27 #define MAX_UNROLL  4
28 
29 #ifdef CONFIG_DEBUG_TCG
30 static const TCGOpcode vecop_list_empty[1] = { 0 };
31 #else
32 #define vecop_list_empty NULL
33 #endif
34 
35 
36 /* Verify vector size and alignment rules.  OFS should be the OR of all
37    of the operand offsets so that we can check them all at once.  */
38 static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
39 {
40     uint32_t opr_align = oprsz >= 16 ? 15 : 7;
41     uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7;
42     tcg_debug_assert(oprsz > 0);
43     tcg_debug_assert(oprsz <= maxsz);
44     tcg_debug_assert((oprsz & opr_align) == 0);
45     tcg_debug_assert((maxsz & max_align) == 0);
46     tcg_debug_assert((ofs & max_align) == 0);
47 }
48 
49 /* Verify vector overlap rules for two operands.  */
50 static void check_overlap_2(uint32_t d, uint32_t a, uint32_t s)
51 {
52     tcg_debug_assert(d == a || d + s <= a || a + s <= d);
53 }
54 
55 /* Verify vector overlap rules for three operands.  */
56 static void check_overlap_3(uint32_t d, uint32_t a, uint32_t b, uint32_t s)
57 {
58     check_overlap_2(d, a, s);
59     check_overlap_2(d, b, s);
60     check_overlap_2(a, b, s);
61 }
62 
63 /* Verify vector overlap rules for four operands.  */
64 static void check_overlap_4(uint32_t d, uint32_t a, uint32_t b,
65                             uint32_t c, uint32_t s)
66 {
67     check_overlap_2(d, a, s);
68     check_overlap_2(d, b, s);
69     check_overlap_2(d, c, s);
70     check_overlap_2(a, b, s);
71     check_overlap_2(a, c, s);
72     check_overlap_2(b, c, s);
73 }
74 
75 /* Create a descriptor from components.  */
76 uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data)
77 {
78     uint32_t desc = 0;
79 
80     assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS));
81     assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS));
82     assert(data == sextract32(data, 0, SIMD_DATA_BITS));
83 
84     oprsz = (oprsz / 8) - 1;
85     maxsz = (maxsz / 8) - 1;
86     desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
87     desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
88     desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
89 
90     return desc;
91 }
92 
93 /* Generate a call to a gvec-style helper with two vector operands.  */
94 void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
95                         uint32_t oprsz, uint32_t maxsz, int32_t data,
96                         gen_helper_gvec_2 *fn)
97 {
98     TCGv_ptr a0, a1;
99     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
100 
101     a0 = tcg_temp_new_ptr();
102     a1 = tcg_temp_new_ptr();
103 
104     tcg_gen_addi_ptr(a0, cpu_env, dofs);
105     tcg_gen_addi_ptr(a1, cpu_env, aofs);
106 
107     fn(a0, a1, desc);
108 
109     tcg_temp_free_ptr(a0);
110     tcg_temp_free_ptr(a1);
111     tcg_temp_free_i32(desc);
112 }
113 
114 /* Generate a call to a gvec-style helper with two vector operands
115    and one scalar operand.  */
116 void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, TCGv_i64 c,
117                          uint32_t oprsz, uint32_t maxsz, int32_t data,
118                          gen_helper_gvec_2i *fn)
119 {
120     TCGv_ptr a0, a1;
121     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
122 
123     a0 = tcg_temp_new_ptr();
124     a1 = tcg_temp_new_ptr();
125 
126     tcg_gen_addi_ptr(a0, cpu_env, dofs);
127     tcg_gen_addi_ptr(a1, cpu_env, aofs);
128 
129     fn(a0, a1, c, desc);
130 
131     tcg_temp_free_ptr(a0);
132     tcg_temp_free_ptr(a1);
133     tcg_temp_free_i32(desc);
134 }
135 
136 /* Generate a call to a gvec-style helper with three vector operands.  */
137 void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
138                         uint32_t oprsz, uint32_t maxsz, int32_t data,
139                         gen_helper_gvec_3 *fn)
140 {
141     TCGv_ptr a0, a1, a2;
142     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
143 
144     a0 = tcg_temp_new_ptr();
145     a1 = tcg_temp_new_ptr();
146     a2 = tcg_temp_new_ptr();
147 
148     tcg_gen_addi_ptr(a0, cpu_env, dofs);
149     tcg_gen_addi_ptr(a1, cpu_env, aofs);
150     tcg_gen_addi_ptr(a2, cpu_env, bofs);
151 
152     fn(a0, a1, a2, desc);
153 
154     tcg_temp_free_ptr(a0);
155     tcg_temp_free_ptr(a1);
156     tcg_temp_free_ptr(a2);
157     tcg_temp_free_i32(desc);
158 }
159 
160 /* Generate a call to a gvec-style helper with four vector operands.  */
161 void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
162                         uint32_t cofs, uint32_t oprsz, uint32_t maxsz,
163                         int32_t data, gen_helper_gvec_4 *fn)
164 {
165     TCGv_ptr a0, a1, a2, a3;
166     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
167 
168     a0 = tcg_temp_new_ptr();
169     a1 = tcg_temp_new_ptr();
170     a2 = tcg_temp_new_ptr();
171     a3 = tcg_temp_new_ptr();
172 
173     tcg_gen_addi_ptr(a0, cpu_env, dofs);
174     tcg_gen_addi_ptr(a1, cpu_env, aofs);
175     tcg_gen_addi_ptr(a2, cpu_env, bofs);
176     tcg_gen_addi_ptr(a3, cpu_env, cofs);
177 
178     fn(a0, a1, a2, a3, desc);
179 
180     tcg_temp_free_ptr(a0);
181     tcg_temp_free_ptr(a1);
182     tcg_temp_free_ptr(a2);
183     tcg_temp_free_ptr(a3);
184     tcg_temp_free_i32(desc);
185 }
186 
187 /* Generate a call to a gvec-style helper with five vector operands.  */
188 void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, uint32_t bofs,
189                         uint32_t cofs, uint32_t xofs, uint32_t oprsz,
190                         uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn)
191 {
192     TCGv_ptr a0, a1, a2, a3, a4;
193     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
194 
195     a0 = tcg_temp_new_ptr();
196     a1 = tcg_temp_new_ptr();
197     a2 = tcg_temp_new_ptr();
198     a3 = tcg_temp_new_ptr();
199     a4 = tcg_temp_new_ptr();
200 
201     tcg_gen_addi_ptr(a0, cpu_env, dofs);
202     tcg_gen_addi_ptr(a1, cpu_env, aofs);
203     tcg_gen_addi_ptr(a2, cpu_env, bofs);
204     tcg_gen_addi_ptr(a3, cpu_env, cofs);
205     tcg_gen_addi_ptr(a4, cpu_env, xofs);
206 
207     fn(a0, a1, a2, a3, a4, desc);
208 
209     tcg_temp_free_ptr(a0);
210     tcg_temp_free_ptr(a1);
211     tcg_temp_free_ptr(a2);
212     tcg_temp_free_ptr(a3);
213     tcg_temp_free_ptr(a4);
214     tcg_temp_free_i32(desc);
215 }
216 
217 /* Generate a call to a gvec-style helper with three vector operands
218    and an extra pointer operand.  */
219 void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
220                         TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
221                         int32_t data, gen_helper_gvec_2_ptr *fn)
222 {
223     TCGv_ptr a0, a1;
224     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
225 
226     a0 = tcg_temp_new_ptr();
227     a1 = tcg_temp_new_ptr();
228 
229     tcg_gen_addi_ptr(a0, cpu_env, dofs);
230     tcg_gen_addi_ptr(a1, cpu_env, aofs);
231 
232     fn(a0, a1, ptr, desc);
233 
234     tcg_temp_free_ptr(a0);
235     tcg_temp_free_ptr(a1);
236     tcg_temp_free_i32(desc);
237 }
238 
239 /* Generate a call to a gvec-style helper with three vector operands
240    and an extra pointer operand.  */
241 void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
242                         TCGv_ptr ptr, uint32_t oprsz, uint32_t maxsz,
243                         int32_t data, gen_helper_gvec_3_ptr *fn)
244 {
245     TCGv_ptr a0, a1, a2;
246     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
247 
248     a0 = tcg_temp_new_ptr();
249     a1 = tcg_temp_new_ptr();
250     a2 = tcg_temp_new_ptr();
251 
252     tcg_gen_addi_ptr(a0, cpu_env, dofs);
253     tcg_gen_addi_ptr(a1, cpu_env, aofs);
254     tcg_gen_addi_ptr(a2, cpu_env, bofs);
255 
256     fn(a0, a1, a2, ptr, desc);
257 
258     tcg_temp_free_ptr(a0);
259     tcg_temp_free_ptr(a1);
260     tcg_temp_free_ptr(a2);
261     tcg_temp_free_i32(desc);
262 }
263 
264 /* Generate a call to a gvec-style helper with four vector operands
265    and an extra pointer operand.  */
266 void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
267                         uint32_t cofs, TCGv_ptr ptr, uint32_t oprsz,
268                         uint32_t maxsz, int32_t data,
269                         gen_helper_gvec_4_ptr *fn)
270 {
271     TCGv_ptr a0, a1, a2, a3;
272     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
273 
274     a0 = tcg_temp_new_ptr();
275     a1 = tcg_temp_new_ptr();
276     a2 = tcg_temp_new_ptr();
277     a3 = tcg_temp_new_ptr();
278 
279     tcg_gen_addi_ptr(a0, cpu_env, dofs);
280     tcg_gen_addi_ptr(a1, cpu_env, aofs);
281     tcg_gen_addi_ptr(a2, cpu_env, bofs);
282     tcg_gen_addi_ptr(a3, cpu_env, cofs);
283 
284     fn(a0, a1, a2, a3, ptr, desc);
285 
286     tcg_temp_free_ptr(a0);
287     tcg_temp_free_ptr(a1);
288     tcg_temp_free_ptr(a2);
289     tcg_temp_free_ptr(a3);
290     tcg_temp_free_i32(desc);
291 }
292 
293 /* Generate a call to a gvec-style helper with five vector operands
294    and an extra pointer operand.  */
295 void tcg_gen_gvec_5_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
296                         uint32_t cofs, uint32_t eofs, TCGv_ptr ptr,
297                         uint32_t oprsz, uint32_t maxsz, int32_t data,
298                         gen_helper_gvec_5_ptr *fn)
299 {
300     TCGv_ptr a0, a1, a2, a3, a4;
301     TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
302 
303     a0 = tcg_temp_new_ptr();
304     a1 = tcg_temp_new_ptr();
305     a2 = tcg_temp_new_ptr();
306     a3 = tcg_temp_new_ptr();
307     a4 = tcg_temp_new_ptr();
308 
309     tcg_gen_addi_ptr(a0, cpu_env, dofs);
310     tcg_gen_addi_ptr(a1, cpu_env, aofs);
311     tcg_gen_addi_ptr(a2, cpu_env, bofs);
312     tcg_gen_addi_ptr(a3, cpu_env, cofs);
313     tcg_gen_addi_ptr(a4, cpu_env, eofs);
314 
315     fn(a0, a1, a2, a3, a4, ptr, desc);
316 
317     tcg_temp_free_ptr(a0);
318     tcg_temp_free_ptr(a1);
319     tcg_temp_free_ptr(a2);
320     tcg_temp_free_ptr(a3);
321     tcg_temp_free_ptr(a4);
322     tcg_temp_free_i32(desc);
323 }
324 
325 /* Return true if we want to implement something of OPRSZ bytes
326    in units of LNSZ.  This limits the expansion of inline code.  */
327 static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz)
328 {
329     uint32_t q, r;
330 
331     if (oprsz < lnsz) {
332         return false;
333     }
334 
335     q = oprsz / lnsz;
336     r = oprsz % lnsz;
337     tcg_debug_assert((r & 7) == 0);
338 
339     if (lnsz < 16) {
340         /* For sizes below 16, accept no remainder. */
341         if (r != 0) {
342             return false;
343         }
344     } else {
345         /*
346          * Recall that ARM SVE allows vector sizes that are not a
347          * power of 2, but always a multiple of 16.  The intent is
348          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
349          * In addition, expand_clr needs to handle a multiple of 8.
350          * Thus we can handle the tail with one more operation per
351          * diminishing power of 2.
352          */
353         q += ctpop32(r);
354     }
355 
356     return q <= MAX_UNROLL;
357 }
358 
359 static void expand_clr(uint32_t dofs, uint32_t maxsz);
360 
361 /* Duplicate C as per VECE.  */
362 uint64_t (dup_const)(unsigned vece, uint64_t c)
363 {
364     switch (vece) {
365     case MO_8:
366         return 0x0101010101010101ull * (uint8_t)c;
367     case MO_16:
368         return 0x0001000100010001ull * (uint16_t)c;
369     case MO_32:
370         return 0x0000000100000001ull * (uint32_t)c;
371     case MO_64:
372         return c;
373     default:
374         g_assert_not_reached();
375     }
376 }
377 
378 /* Duplicate IN into OUT as per VECE.  */
379 static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
380 {
381     switch (vece) {
382     case MO_8:
383         tcg_gen_ext8u_i32(out, in);
384         tcg_gen_muli_i32(out, out, 0x01010101);
385         break;
386     case MO_16:
387         tcg_gen_deposit_i32(out, in, in, 16, 16);
388         break;
389     case MO_32:
390         tcg_gen_mov_i32(out, in);
391         break;
392     default:
393         g_assert_not_reached();
394     }
395 }
396 
397 static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
398 {
399     switch (vece) {
400     case MO_8:
401         tcg_gen_ext8u_i64(out, in);
402         tcg_gen_muli_i64(out, out, 0x0101010101010101ull);
403         break;
404     case MO_16:
405         tcg_gen_ext16u_i64(out, in);
406         tcg_gen_muli_i64(out, out, 0x0001000100010001ull);
407         break;
408     case MO_32:
409         tcg_gen_deposit_i64(out, in, in, 32, 32);
410         break;
411     case MO_64:
412         tcg_gen_mov_i64(out, in);
413         break;
414     default:
415         g_assert_not_reached();
416     }
417 }
418 
419 /* Select a supported vector type for implementing an operation on SIZE
420  * bytes.  If OP is 0, assume that the real operation to be performed is
421  * required by all backends.  Otherwise, make sure than OP can be performed
422  * on elements of size VECE in the selected type.  Do not select V64 if
423  * PREFER_I64 is true.  Return 0 if no vector type is selected.
424  */
425 static TCGType choose_vector_type(const TCGOpcode *list, unsigned vece,
426                                   uint32_t size, bool prefer_i64)
427 {
428     /*
429      * Recall that ARM SVE allows vector sizes that are not a
430      * power of 2, but always a multiple of 16.  The intent is
431      * that e.g. size == 80 would be expanded with 2x32 + 1x16.
432      * It is hard to imagine a case in which v256 is supported
433      * but v128 is not, but check anyway.
434      * In addition, expand_clr needs to handle a multiple of 8.
435      */
436     if (TCG_TARGET_HAS_v256 &&
437         check_size_impl(size, 32) &&
438         tcg_can_emit_vecop_list(list, TCG_TYPE_V256, vece) &&
439         (!(size & 16) ||
440          (TCG_TARGET_HAS_v128 &&
441           tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece))) &&
442         (!(size & 8) ||
443          (TCG_TARGET_HAS_v64 &&
444           tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) {
445         return TCG_TYPE_V256;
446     }
447     if (TCG_TARGET_HAS_v128 &&
448         check_size_impl(size, 16) &&
449         tcg_can_emit_vecop_list(list, TCG_TYPE_V128, vece) &&
450         (!(size & 8) ||
451          (TCG_TARGET_HAS_v64 &&
452           tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)))) {
453         return TCG_TYPE_V128;
454     }
455     if (TCG_TARGET_HAS_v64 && !prefer_i64 && check_size_impl(size, 8)
456         && tcg_can_emit_vecop_list(list, TCG_TYPE_V64, vece)) {
457         return TCG_TYPE_V64;
458     }
459     return 0;
460 }
461 
462 static void do_dup_store(TCGType type, uint32_t dofs, uint32_t oprsz,
463                          uint32_t maxsz, TCGv_vec t_vec)
464 {
465     uint32_t i = 0;
466 
467     tcg_debug_assert(oprsz >= 8);
468 
469     /*
470      * This may be expand_clr for the tail of an operation, e.g.
471      * oprsz == 8 && maxsz == 64.  The first 8 bytes of this store
472      * are misaligned wrt the maximum vector size, so do that first.
473      */
474     if (dofs & 8) {
475         tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64);
476         i += 8;
477     }
478 
479     switch (type) {
480     case TCG_TYPE_V256:
481         /*
482          * Recall that ARM SVE allows vector sizes that are not a
483          * power of 2, but always a multiple of 16.  The intent is
484          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
485          */
486         for (; i + 32 <= oprsz; i += 32) {
487             tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V256);
488         }
489         /* fallthru */
490     case TCG_TYPE_V128:
491         for (; i + 16 <= oprsz; i += 16) {
492             tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V128);
493         }
494         break;
495     case TCG_TYPE_V64:
496         for (; i < oprsz; i += 8) {
497             tcg_gen_stl_vec(t_vec, cpu_env, dofs + i, TCG_TYPE_V64);
498         }
499         break;
500     default:
501         g_assert_not_reached();
502     }
503 
504     if (oprsz < maxsz) {
505         expand_clr(dofs + oprsz, maxsz - oprsz);
506     }
507 }
508 
509 /* Set OPRSZ bytes at DOFS to replications of IN_32, IN_64 or IN_C.
510  * Only one of IN_32 or IN_64 may be set;
511  * IN_C is used if IN_32 and IN_64 are unset.
512  */
513 static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz,
514                    uint32_t maxsz, TCGv_i32 in_32, TCGv_i64 in_64,
515                    uint64_t in_c)
516 {
517     TCGType type;
518     TCGv_i64 t_64;
519     TCGv_i32 t_32, t_desc;
520     TCGv_ptr t_ptr;
521     uint32_t i;
522 
523     assert(vece <= (in_32 ? MO_32 : MO_64));
524     assert(in_32 == NULL || in_64 == NULL);
525 
526     /* If we're storing 0, expand oprsz to maxsz.  */
527     if (in_32 == NULL && in_64 == NULL) {
528         in_c = dup_const(vece, in_c);
529         if (in_c == 0) {
530             oprsz = maxsz;
531         }
532     }
533 
534     /* Implement inline with a vector type, if possible.
535      * Prefer integer when 64-bit host and no variable dup.
536      */
537     type = choose_vector_type(NULL, vece, oprsz,
538                               (TCG_TARGET_REG_BITS == 64 && in_32 == NULL
539                                && (in_64 == NULL || vece == MO_64)));
540     if (type != 0) {
541         TCGv_vec t_vec = tcg_temp_new_vec(type);
542 
543         if (in_32) {
544             tcg_gen_dup_i32_vec(vece, t_vec, in_32);
545         } else if (in_64) {
546             tcg_gen_dup_i64_vec(vece, t_vec, in_64);
547         } else {
548             tcg_gen_dupi_vec(vece, t_vec, in_c);
549         }
550         do_dup_store(type, dofs, oprsz, maxsz, t_vec);
551         tcg_temp_free_vec(t_vec);
552         return;
553     }
554 
555     /* Otherwise, inline with an integer type, unless "large".  */
556     if (check_size_impl(oprsz, TCG_TARGET_REG_BITS / 8)) {
557         t_64 = NULL;
558         t_32 = NULL;
559 
560         if (in_32) {
561             /* We are given a 32-bit variable input.  For a 64-bit host,
562                use a 64-bit operation unless the 32-bit operation would
563                be simple enough.  */
564             if (TCG_TARGET_REG_BITS == 64
565                 && (vece != MO_32 || !check_size_impl(oprsz, 4))) {
566                 t_64 = tcg_temp_new_i64();
567                 tcg_gen_extu_i32_i64(t_64, in_32);
568                 gen_dup_i64(vece, t_64, t_64);
569             } else {
570                 t_32 = tcg_temp_new_i32();
571                 gen_dup_i32(vece, t_32, in_32);
572             }
573         } else if (in_64) {
574             /* We are given a 64-bit variable input.  */
575             t_64 = tcg_temp_new_i64();
576             gen_dup_i64(vece, t_64, in_64);
577         } else {
578             /* We are given a constant input.  */
579             /* For 64-bit hosts, use 64-bit constants for "simple" constants
580                or when we'd need too many 32-bit stores, or when a 64-bit
581                constant is really required.  */
582             if (vece == MO_64
583                 || (TCG_TARGET_REG_BITS == 64
584                     && (in_c == 0 || in_c == -1
585                         || !check_size_impl(oprsz, 4)))) {
586                 t_64 = tcg_const_i64(in_c);
587             } else {
588                 t_32 = tcg_const_i32(in_c);
589             }
590         }
591 
592         /* Implement inline if we picked an implementation size above.  */
593         if (t_32) {
594             for (i = 0; i < oprsz; i += 4) {
595                 tcg_gen_st_i32(t_32, cpu_env, dofs + i);
596             }
597             tcg_temp_free_i32(t_32);
598             goto done;
599         }
600         if (t_64) {
601             for (i = 0; i < oprsz; i += 8) {
602                 tcg_gen_st_i64(t_64, cpu_env, dofs + i);
603             }
604             tcg_temp_free_i64(t_64);
605             goto done;
606         }
607     }
608 
609     /* Otherwise implement out of line.  */
610     t_ptr = tcg_temp_new_ptr();
611     tcg_gen_addi_ptr(t_ptr, cpu_env, dofs);
612     t_desc = tcg_const_i32(simd_desc(oprsz, maxsz, 0));
613 
614     if (vece == MO_64) {
615         if (in_64) {
616             gen_helper_gvec_dup64(t_ptr, t_desc, in_64);
617         } else {
618             t_64 = tcg_const_i64(in_c);
619             gen_helper_gvec_dup64(t_ptr, t_desc, t_64);
620             tcg_temp_free_i64(t_64);
621         }
622     } else {
623         typedef void dup_fn(TCGv_ptr, TCGv_i32, TCGv_i32);
624         static dup_fn * const fns[3] = {
625             gen_helper_gvec_dup8,
626             gen_helper_gvec_dup16,
627             gen_helper_gvec_dup32
628         };
629 
630         if (in_32) {
631             fns[vece](t_ptr, t_desc, in_32);
632         } else {
633             t_32 = tcg_temp_new_i32();
634             if (in_64) {
635                 tcg_gen_extrl_i64_i32(t_32, in_64);
636             } else if (vece == MO_8) {
637                 tcg_gen_movi_i32(t_32, in_c & 0xff);
638             } else if (vece == MO_16) {
639                 tcg_gen_movi_i32(t_32, in_c & 0xffff);
640             } else {
641                 tcg_gen_movi_i32(t_32, in_c);
642             }
643             fns[vece](t_ptr, t_desc, t_32);
644             tcg_temp_free_i32(t_32);
645         }
646     }
647 
648     tcg_temp_free_ptr(t_ptr);
649     tcg_temp_free_i32(t_desc);
650     return;
651 
652  done:
653     if (oprsz < maxsz) {
654         expand_clr(dofs + oprsz, maxsz - oprsz);
655     }
656 }
657 
658 /* Likewise, but with zero.  */
659 static void expand_clr(uint32_t dofs, uint32_t maxsz)
660 {
661     do_dup(MO_8, dofs, maxsz, maxsz, NULL, NULL, 0);
662 }
663 
664 /* Expand OPSZ bytes worth of two-operand operations using i32 elements.  */
665 static void expand_2_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
666                          bool load_dest, void (*fni)(TCGv_i32, TCGv_i32))
667 {
668     TCGv_i32 t0 = tcg_temp_new_i32();
669     TCGv_i32 t1 = tcg_temp_new_i32();
670     uint32_t i;
671 
672     for (i = 0; i < oprsz; i += 4) {
673         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
674         if (load_dest) {
675             tcg_gen_ld_i32(t1, cpu_env, dofs + i);
676         }
677         fni(t1, t0);
678         tcg_gen_st_i32(t1, cpu_env, dofs + i);
679     }
680     tcg_temp_free_i32(t0);
681     tcg_temp_free_i32(t1);
682 }
683 
684 static void expand_2i_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
685                           int32_t c, bool load_dest,
686                           void (*fni)(TCGv_i32, TCGv_i32, int32_t))
687 {
688     TCGv_i32 t0 = tcg_temp_new_i32();
689     TCGv_i32 t1 = tcg_temp_new_i32();
690     uint32_t i;
691 
692     for (i = 0; i < oprsz; i += 4) {
693         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
694         if (load_dest) {
695             tcg_gen_ld_i32(t1, cpu_env, dofs + i);
696         }
697         fni(t1, t0, c);
698         tcg_gen_st_i32(t1, cpu_env, dofs + i);
699     }
700     tcg_temp_free_i32(t0);
701     tcg_temp_free_i32(t1);
702 }
703 
704 static void expand_2s_i32(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
705                           TCGv_i32 c, bool scalar_first,
706                           void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32))
707 {
708     TCGv_i32 t0 = tcg_temp_new_i32();
709     TCGv_i32 t1 = tcg_temp_new_i32();
710     uint32_t i;
711 
712     for (i = 0; i < oprsz; i += 4) {
713         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
714         if (scalar_first) {
715             fni(t1, c, t0);
716         } else {
717             fni(t1, t0, c);
718         }
719         tcg_gen_st_i32(t1, cpu_env, dofs + i);
720     }
721     tcg_temp_free_i32(t0);
722     tcg_temp_free_i32(t1);
723 }
724 
725 /* Expand OPSZ bytes worth of three-operand operations using i32 elements.  */
726 static void expand_3_i32(uint32_t dofs, uint32_t aofs,
727                          uint32_t bofs, uint32_t oprsz, bool load_dest,
728                          void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32))
729 {
730     TCGv_i32 t0 = tcg_temp_new_i32();
731     TCGv_i32 t1 = tcg_temp_new_i32();
732     TCGv_i32 t2 = tcg_temp_new_i32();
733     uint32_t i;
734 
735     for (i = 0; i < oprsz; i += 4) {
736         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
737         tcg_gen_ld_i32(t1, cpu_env, bofs + i);
738         if (load_dest) {
739             tcg_gen_ld_i32(t2, cpu_env, dofs + i);
740         }
741         fni(t2, t0, t1);
742         tcg_gen_st_i32(t2, cpu_env, dofs + i);
743     }
744     tcg_temp_free_i32(t2);
745     tcg_temp_free_i32(t1);
746     tcg_temp_free_i32(t0);
747 }
748 
749 static void expand_3i_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
750                           uint32_t oprsz, int32_t c, bool load_dest,
751                           void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, int32_t))
752 {
753     TCGv_i32 t0 = tcg_temp_new_i32();
754     TCGv_i32 t1 = tcg_temp_new_i32();
755     TCGv_i32 t2 = tcg_temp_new_i32();
756     uint32_t i;
757 
758     for (i = 0; i < oprsz; i += 4) {
759         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
760         tcg_gen_ld_i32(t1, cpu_env, bofs + i);
761         if (load_dest) {
762             tcg_gen_ld_i32(t2, cpu_env, dofs + i);
763         }
764         fni(t2, t0, t1, c);
765         tcg_gen_st_i32(t2, cpu_env, dofs + i);
766     }
767     tcg_temp_free_i32(t0);
768     tcg_temp_free_i32(t1);
769     tcg_temp_free_i32(t2);
770 }
771 
772 /* Expand OPSZ bytes worth of three-operand operations using i32 elements.  */
773 static void expand_4_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
774                          uint32_t cofs, uint32_t oprsz, bool write_aofs,
775                          void (*fni)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
776 {
777     TCGv_i32 t0 = tcg_temp_new_i32();
778     TCGv_i32 t1 = tcg_temp_new_i32();
779     TCGv_i32 t2 = tcg_temp_new_i32();
780     TCGv_i32 t3 = tcg_temp_new_i32();
781     uint32_t i;
782 
783     for (i = 0; i < oprsz; i += 4) {
784         tcg_gen_ld_i32(t1, cpu_env, aofs + i);
785         tcg_gen_ld_i32(t2, cpu_env, bofs + i);
786         tcg_gen_ld_i32(t3, cpu_env, cofs + i);
787         fni(t0, t1, t2, t3);
788         tcg_gen_st_i32(t0, cpu_env, dofs + i);
789         if (write_aofs) {
790             tcg_gen_st_i32(t1, cpu_env, aofs + i);
791         }
792     }
793     tcg_temp_free_i32(t3);
794     tcg_temp_free_i32(t2);
795     tcg_temp_free_i32(t1);
796     tcg_temp_free_i32(t0);
797 }
798 
799 /* Expand OPSZ bytes worth of two-operand operations using i64 elements.  */
800 static void expand_2_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
801                          bool load_dest, void (*fni)(TCGv_i64, TCGv_i64))
802 {
803     TCGv_i64 t0 = tcg_temp_new_i64();
804     TCGv_i64 t1 = tcg_temp_new_i64();
805     uint32_t i;
806 
807     for (i = 0; i < oprsz; i += 8) {
808         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
809         if (load_dest) {
810             tcg_gen_ld_i64(t1, cpu_env, dofs + i);
811         }
812         fni(t1, t0);
813         tcg_gen_st_i64(t1, cpu_env, dofs + i);
814     }
815     tcg_temp_free_i64(t0);
816     tcg_temp_free_i64(t1);
817 }
818 
819 static void expand_2i_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
820                           int64_t c, bool load_dest,
821                           void (*fni)(TCGv_i64, TCGv_i64, int64_t))
822 {
823     TCGv_i64 t0 = tcg_temp_new_i64();
824     TCGv_i64 t1 = tcg_temp_new_i64();
825     uint32_t i;
826 
827     for (i = 0; i < oprsz; i += 8) {
828         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
829         if (load_dest) {
830             tcg_gen_ld_i64(t1, cpu_env, dofs + i);
831         }
832         fni(t1, t0, c);
833         tcg_gen_st_i64(t1, cpu_env, dofs + i);
834     }
835     tcg_temp_free_i64(t0);
836     tcg_temp_free_i64(t1);
837 }
838 
839 static void expand_2s_i64(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
840                           TCGv_i64 c, bool scalar_first,
841                           void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64))
842 {
843     TCGv_i64 t0 = tcg_temp_new_i64();
844     TCGv_i64 t1 = tcg_temp_new_i64();
845     uint32_t i;
846 
847     for (i = 0; i < oprsz; i += 8) {
848         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
849         if (scalar_first) {
850             fni(t1, c, t0);
851         } else {
852             fni(t1, t0, c);
853         }
854         tcg_gen_st_i64(t1, cpu_env, dofs + i);
855     }
856     tcg_temp_free_i64(t0);
857     tcg_temp_free_i64(t1);
858 }
859 
860 /* Expand OPSZ bytes worth of three-operand operations using i64 elements.  */
861 static void expand_3_i64(uint32_t dofs, uint32_t aofs,
862                          uint32_t bofs, uint32_t oprsz, bool load_dest,
863                          void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64))
864 {
865     TCGv_i64 t0 = tcg_temp_new_i64();
866     TCGv_i64 t1 = tcg_temp_new_i64();
867     TCGv_i64 t2 = tcg_temp_new_i64();
868     uint32_t i;
869 
870     for (i = 0; i < oprsz; i += 8) {
871         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
872         tcg_gen_ld_i64(t1, cpu_env, bofs + i);
873         if (load_dest) {
874             tcg_gen_ld_i64(t2, cpu_env, dofs + i);
875         }
876         fni(t2, t0, t1);
877         tcg_gen_st_i64(t2, cpu_env, dofs + i);
878     }
879     tcg_temp_free_i64(t2);
880     tcg_temp_free_i64(t1);
881     tcg_temp_free_i64(t0);
882 }
883 
884 static void expand_3i_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
885                           uint32_t oprsz, int64_t c, bool load_dest,
886                           void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, int64_t))
887 {
888     TCGv_i64 t0 = tcg_temp_new_i64();
889     TCGv_i64 t1 = tcg_temp_new_i64();
890     TCGv_i64 t2 = tcg_temp_new_i64();
891     uint32_t i;
892 
893     for (i = 0; i < oprsz; i += 8) {
894         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
895         tcg_gen_ld_i64(t1, cpu_env, bofs + i);
896         if (load_dest) {
897             tcg_gen_ld_i64(t2, cpu_env, dofs + i);
898         }
899         fni(t2, t0, t1, c);
900         tcg_gen_st_i64(t2, cpu_env, dofs + i);
901     }
902     tcg_temp_free_i64(t0);
903     tcg_temp_free_i64(t1);
904     tcg_temp_free_i64(t2);
905 }
906 
907 /* Expand OPSZ bytes worth of three-operand operations using i64 elements.  */
908 static void expand_4_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
909                          uint32_t cofs, uint32_t oprsz, bool write_aofs,
910                          void (*fni)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
911 {
912     TCGv_i64 t0 = tcg_temp_new_i64();
913     TCGv_i64 t1 = tcg_temp_new_i64();
914     TCGv_i64 t2 = tcg_temp_new_i64();
915     TCGv_i64 t3 = tcg_temp_new_i64();
916     uint32_t i;
917 
918     for (i = 0; i < oprsz; i += 8) {
919         tcg_gen_ld_i64(t1, cpu_env, aofs + i);
920         tcg_gen_ld_i64(t2, cpu_env, bofs + i);
921         tcg_gen_ld_i64(t3, cpu_env, cofs + i);
922         fni(t0, t1, t2, t3);
923         tcg_gen_st_i64(t0, cpu_env, dofs + i);
924         if (write_aofs) {
925             tcg_gen_st_i64(t1, cpu_env, aofs + i);
926         }
927     }
928     tcg_temp_free_i64(t3);
929     tcg_temp_free_i64(t2);
930     tcg_temp_free_i64(t1);
931     tcg_temp_free_i64(t0);
932 }
933 
934 /* Expand OPSZ bytes worth of two-operand operations using host vectors.  */
935 static void expand_2_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
936                          uint32_t oprsz, uint32_t tysz, TCGType type,
937                          bool load_dest,
938                          void (*fni)(unsigned, TCGv_vec, TCGv_vec))
939 {
940     TCGv_vec t0 = tcg_temp_new_vec(type);
941     TCGv_vec t1 = tcg_temp_new_vec(type);
942     uint32_t i;
943 
944     for (i = 0; i < oprsz; i += tysz) {
945         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
946         if (load_dest) {
947             tcg_gen_ld_vec(t1, cpu_env, dofs + i);
948         }
949         fni(vece, t1, t0);
950         tcg_gen_st_vec(t1, cpu_env, dofs + i);
951     }
952     tcg_temp_free_vec(t0);
953     tcg_temp_free_vec(t1);
954 }
955 
956 /* Expand OPSZ bytes worth of two-vector operands and an immediate operand
957    using host vectors.  */
958 static void expand_2i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
959                           uint32_t oprsz, uint32_t tysz, TCGType type,
960                           int64_t c, bool load_dest,
961                           void (*fni)(unsigned, TCGv_vec, TCGv_vec, int64_t))
962 {
963     TCGv_vec t0 = tcg_temp_new_vec(type);
964     TCGv_vec t1 = tcg_temp_new_vec(type);
965     uint32_t i;
966 
967     for (i = 0; i < oprsz; i += tysz) {
968         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
969         if (load_dest) {
970             tcg_gen_ld_vec(t1, cpu_env, dofs + i);
971         }
972         fni(vece, t1, t0, c);
973         tcg_gen_st_vec(t1, cpu_env, dofs + i);
974     }
975     tcg_temp_free_vec(t0);
976     tcg_temp_free_vec(t1);
977 }
978 
979 static void expand_2s_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
980                           uint32_t oprsz, uint32_t tysz, TCGType type,
981                           TCGv_vec c, bool scalar_first,
982                           void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
983 {
984     TCGv_vec t0 = tcg_temp_new_vec(type);
985     TCGv_vec t1 = tcg_temp_new_vec(type);
986     uint32_t i;
987 
988     for (i = 0; i < oprsz; i += tysz) {
989         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
990         if (scalar_first) {
991             fni(vece, t1, c, t0);
992         } else {
993             fni(vece, t1, t0, c);
994         }
995         tcg_gen_st_vec(t1, cpu_env, dofs + i);
996     }
997     tcg_temp_free_vec(t0);
998     tcg_temp_free_vec(t1);
999 }
1000 
1001 /* Expand OPSZ bytes worth of three-operand operations using host vectors.  */
1002 static void expand_3_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
1003                          uint32_t bofs, uint32_t oprsz,
1004                          uint32_t tysz, TCGType type, bool load_dest,
1005                          void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
1006 {
1007     TCGv_vec t0 = tcg_temp_new_vec(type);
1008     TCGv_vec t1 = tcg_temp_new_vec(type);
1009     TCGv_vec t2 = tcg_temp_new_vec(type);
1010     uint32_t i;
1011 
1012     for (i = 0; i < oprsz; i += tysz) {
1013         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
1014         tcg_gen_ld_vec(t1, cpu_env, bofs + i);
1015         if (load_dest) {
1016             tcg_gen_ld_vec(t2, cpu_env, dofs + i);
1017         }
1018         fni(vece, t2, t0, t1);
1019         tcg_gen_st_vec(t2, cpu_env, dofs + i);
1020     }
1021     tcg_temp_free_vec(t2);
1022     tcg_temp_free_vec(t1);
1023     tcg_temp_free_vec(t0);
1024 }
1025 
1026 /*
1027  * Expand OPSZ bytes worth of three-vector operands and an immediate operand
1028  * using host vectors.
1029  */
1030 static void expand_3i_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
1031                           uint32_t bofs, uint32_t oprsz, uint32_t tysz,
1032                           TCGType type, int64_t c, bool load_dest,
1033                           void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec,
1034                                       int64_t))
1035 {
1036     TCGv_vec t0 = tcg_temp_new_vec(type);
1037     TCGv_vec t1 = tcg_temp_new_vec(type);
1038     TCGv_vec t2 = tcg_temp_new_vec(type);
1039     uint32_t i;
1040 
1041     for (i = 0; i < oprsz; i += tysz) {
1042         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
1043         tcg_gen_ld_vec(t1, cpu_env, bofs + i);
1044         if (load_dest) {
1045             tcg_gen_ld_vec(t2, cpu_env, dofs + i);
1046         }
1047         fni(vece, t2, t0, t1, c);
1048         tcg_gen_st_vec(t2, cpu_env, dofs + i);
1049     }
1050     tcg_temp_free_vec(t0);
1051     tcg_temp_free_vec(t1);
1052     tcg_temp_free_vec(t2);
1053 }
1054 
1055 /* Expand OPSZ bytes worth of four-operand operations using host vectors.  */
1056 static void expand_4_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
1057                          uint32_t bofs, uint32_t cofs, uint32_t oprsz,
1058                          uint32_t tysz, TCGType type, bool write_aofs,
1059                          void (*fni)(unsigned, TCGv_vec, TCGv_vec,
1060                                      TCGv_vec, TCGv_vec))
1061 {
1062     TCGv_vec t0 = tcg_temp_new_vec(type);
1063     TCGv_vec t1 = tcg_temp_new_vec(type);
1064     TCGv_vec t2 = tcg_temp_new_vec(type);
1065     TCGv_vec t3 = tcg_temp_new_vec(type);
1066     uint32_t i;
1067 
1068     for (i = 0; i < oprsz; i += tysz) {
1069         tcg_gen_ld_vec(t1, cpu_env, aofs + i);
1070         tcg_gen_ld_vec(t2, cpu_env, bofs + i);
1071         tcg_gen_ld_vec(t3, cpu_env, cofs + i);
1072         fni(vece, t0, t1, t2, t3);
1073         tcg_gen_st_vec(t0, cpu_env, dofs + i);
1074         if (write_aofs) {
1075             tcg_gen_st_vec(t1, cpu_env, aofs + i);
1076         }
1077     }
1078     tcg_temp_free_vec(t3);
1079     tcg_temp_free_vec(t2);
1080     tcg_temp_free_vec(t1);
1081     tcg_temp_free_vec(t0);
1082 }
1083 
1084 /* Expand a vector two-operand operation.  */
1085 void tcg_gen_gvec_2(uint32_t dofs, uint32_t aofs,
1086                     uint32_t oprsz, uint32_t maxsz, const GVecGen2 *g)
1087 {
1088     const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1089     const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1090     TCGType type;
1091     uint32_t some;
1092 
1093     check_size_align(oprsz, maxsz, dofs | aofs);
1094     check_overlap_2(dofs, aofs, maxsz);
1095 
1096     type = 0;
1097     if (g->fniv) {
1098         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1099     }
1100     switch (type) {
1101     case TCG_TYPE_V256:
1102         /* Recall that ARM SVE allows vector sizes that are not a
1103          * power of 2, but always a multiple of 16.  The intent is
1104          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1105          */
1106         some = QEMU_ALIGN_DOWN(oprsz, 32);
1107         expand_2_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
1108                      g->load_dest, g->fniv);
1109         if (some == oprsz) {
1110             break;
1111         }
1112         dofs += some;
1113         aofs += some;
1114         oprsz -= some;
1115         maxsz -= some;
1116         /* fallthru */
1117     case TCG_TYPE_V128:
1118         expand_2_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
1119                      g->load_dest, g->fniv);
1120         break;
1121     case TCG_TYPE_V64:
1122         expand_2_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
1123                      g->load_dest, g->fniv);
1124         break;
1125 
1126     case 0:
1127         if (g->fni8 && check_size_impl(oprsz, 8)) {
1128             expand_2_i64(dofs, aofs, oprsz, g->load_dest, g->fni8);
1129         } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1130             expand_2_i32(dofs, aofs, oprsz, g->load_dest, g->fni4);
1131         } else {
1132             assert(g->fno != NULL);
1133             tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, g->data, g->fno);
1134             oprsz = maxsz;
1135         }
1136         break;
1137 
1138     default:
1139         g_assert_not_reached();
1140     }
1141     tcg_swap_vecop_list(hold_list);
1142 
1143     if (oprsz < maxsz) {
1144         expand_clr(dofs + oprsz, maxsz - oprsz);
1145     }
1146 }
1147 
1148 /* Expand a vector operation with two vectors and an immediate.  */
1149 void tcg_gen_gvec_2i(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
1150                      uint32_t maxsz, int64_t c, const GVecGen2i *g)
1151 {
1152     const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1153     const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1154     TCGType type;
1155     uint32_t some;
1156 
1157     check_size_align(oprsz, maxsz, dofs | aofs);
1158     check_overlap_2(dofs, aofs, maxsz);
1159 
1160     type = 0;
1161     if (g->fniv) {
1162         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1163     }
1164     switch (type) {
1165     case TCG_TYPE_V256:
1166         /* Recall that ARM SVE allows vector sizes that are not a
1167          * power of 2, but always a multiple of 16.  The intent is
1168          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1169          */
1170         some = QEMU_ALIGN_DOWN(oprsz, 32);
1171         expand_2i_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
1172                       c, g->load_dest, g->fniv);
1173         if (some == oprsz) {
1174             break;
1175         }
1176         dofs += some;
1177         aofs += some;
1178         oprsz -= some;
1179         maxsz -= some;
1180         /* fallthru */
1181     case TCG_TYPE_V128:
1182         expand_2i_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
1183                       c, g->load_dest, g->fniv);
1184         break;
1185     case TCG_TYPE_V64:
1186         expand_2i_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
1187                       c, g->load_dest, g->fniv);
1188         break;
1189 
1190     case 0:
1191         if (g->fni8 && check_size_impl(oprsz, 8)) {
1192             expand_2i_i64(dofs, aofs, oprsz, c, g->load_dest, g->fni8);
1193         } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1194             expand_2i_i32(dofs, aofs, oprsz, c, g->load_dest, g->fni4);
1195         } else {
1196             if (g->fno) {
1197                 tcg_gen_gvec_2_ool(dofs, aofs, oprsz, maxsz, c, g->fno);
1198             } else {
1199                 TCGv_i64 tcg_c = tcg_const_i64(c);
1200                 tcg_gen_gvec_2i_ool(dofs, aofs, tcg_c, oprsz,
1201                                     maxsz, c, g->fnoi);
1202                 tcg_temp_free_i64(tcg_c);
1203             }
1204             oprsz = maxsz;
1205         }
1206         break;
1207 
1208     default:
1209         g_assert_not_reached();
1210     }
1211     tcg_swap_vecop_list(hold_list);
1212 
1213     if (oprsz < maxsz) {
1214         expand_clr(dofs + oprsz, maxsz - oprsz);
1215     }
1216 }
1217 
1218 /* Expand a vector operation with two vectors and a scalar.  */
1219 void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
1220                      uint32_t maxsz, TCGv_i64 c, const GVecGen2s *g)
1221 {
1222     TCGType type;
1223 
1224     check_size_align(oprsz, maxsz, dofs | aofs);
1225     check_overlap_2(dofs, aofs, maxsz);
1226 
1227     type = 0;
1228     if (g->fniv) {
1229         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1230     }
1231     if (type != 0) {
1232         const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1233         const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1234         TCGv_vec t_vec = tcg_temp_new_vec(type);
1235         uint32_t some;
1236 
1237         tcg_gen_dup_i64_vec(g->vece, t_vec, c);
1238 
1239         switch (type) {
1240         case TCG_TYPE_V256:
1241             /* Recall that ARM SVE allows vector sizes that are not a
1242              * power of 2, but always a multiple of 16.  The intent is
1243              * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1244              */
1245             some = QEMU_ALIGN_DOWN(oprsz, 32);
1246             expand_2s_vec(g->vece, dofs, aofs, some, 32, TCG_TYPE_V256,
1247                           t_vec, g->scalar_first, g->fniv);
1248             if (some == oprsz) {
1249                 break;
1250             }
1251             dofs += some;
1252             aofs += some;
1253             oprsz -= some;
1254             maxsz -= some;
1255             /* fallthru */
1256 
1257         case TCG_TYPE_V128:
1258             expand_2s_vec(g->vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
1259                           t_vec, g->scalar_first, g->fniv);
1260             break;
1261 
1262         case TCG_TYPE_V64:
1263             expand_2s_vec(g->vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
1264                           t_vec, g->scalar_first, g->fniv);
1265             break;
1266 
1267         default:
1268             g_assert_not_reached();
1269         }
1270         tcg_temp_free_vec(t_vec);
1271         tcg_swap_vecop_list(hold_list);
1272     } else if (g->fni8 && check_size_impl(oprsz, 8)) {
1273         TCGv_i64 t64 = tcg_temp_new_i64();
1274 
1275         gen_dup_i64(g->vece, t64, c);
1276         expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
1277         tcg_temp_free_i64(t64);
1278     } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1279         TCGv_i32 t32 = tcg_temp_new_i32();
1280 
1281         tcg_gen_extrl_i64_i32(t32, c);
1282         gen_dup_i32(g->vece, t32, t32);
1283         expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
1284         tcg_temp_free_i32(t32);
1285     } else {
1286         tcg_gen_gvec_2i_ool(dofs, aofs, c, oprsz, maxsz, 0, g->fno);
1287         return;
1288     }
1289 
1290     if (oprsz < maxsz) {
1291         expand_clr(dofs + oprsz, maxsz - oprsz);
1292     }
1293 }
1294 
1295 /* Expand a vector three-operand operation.  */
1296 void tcg_gen_gvec_3(uint32_t dofs, uint32_t aofs, uint32_t bofs,
1297                     uint32_t oprsz, uint32_t maxsz, const GVecGen3 *g)
1298 {
1299     const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1300     const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1301     TCGType type;
1302     uint32_t some;
1303 
1304     check_size_align(oprsz, maxsz, dofs | aofs | bofs);
1305     check_overlap_3(dofs, aofs, bofs, maxsz);
1306 
1307     type = 0;
1308     if (g->fniv) {
1309         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1310     }
1311     switch (type) {
1312     case TCG_TYPE_V256:
1313         /* Recall that ARM SVE allows vector sizes that are not a
1314          * power of 2, but always a multiple of 16.  The intent is
1315          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1316          */
1317         some = QEMU_ALIGN_DOWN(oprsz, 32);
1318         expand_3_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256,
1319                      g->load_dest, g->fniv);
1320         if (some == oprsz) {
1321             break;
1322         }
1323         dofs += some;
1324         aofs += some;
1325         bofs += some;
1326         oprsz -= some;
1327         maxsz -= some;
1328         /* fallthru */
1329     case TCG_TYPE_V128:
1330         expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128,
1331                      g->load_dest, g->fniv);
1332         break;
1333     case TCG_TYPE_V64:
1334         expand_3_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64,
1335                      g->load_dest, g->fniv);
1336         break;
1337 
1338     case 0:
1339         if (g->fni8 && check_size_impl(oprsz, 8)) {
1340             expand_3_i64(dofs, aofs, bofs, oprsz, g->load_dest, g->fni8);
1341         } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1342             expand_3_i32(dofs, aofs, bofs, oprsz, g->load_dest, g->fni4);
1343         } else {
1344             assert(g->fno != NULL);
1345             tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz,
1346                                maxsz, g->data, g->fno);
1347             oprsz = maxsz;
1348         }
1349         break;
1350 
1351     default:
1352         g_assert_not_reached();
1353     }
1354     tcg_swap_vecop_list(hold_list);
1355 
1356     if (oprsz < maxsz) {
1357         expand_clr(dofs + oprsz, maxsz - oprsz);
1358     }
1359 }
1360 
1361 /* Expand a vector operation with three vectors and an immediate.  */
1362 void tcg_gen_gvec_3i(uint32_t dofs, uint32_t aofs, uint32_t bofs,
1363                      uint32_t oprsz, uint32_t maxsz, int64_t c,
1364                      const GVecGen3i *g)
1365 {
1366     const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1367     const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1368     TCGType type;
1369     uint32_t some;
1370 
1371     check_size_align(oprsz, maxsz, dofs | aofs | bofs);
1372     check_overlap_3(dofs, aofs, bofs, maxsz);
1373 
1374     type = 0;
1375     if (g->fniv) {
1376         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1377     }
1378     switch (type) {
1379     case TCG_TYPE_V256:
1380         /*
1381          * Recall that ARM SVE allows vector sizes that are not a
1382          * power of 2, but always a multiple of 16.  The intent is
1383          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1384          */
1385         some = QEMU_ALIGN_DOWN(oprsz, 32);
1386         expand_3i_vec(g->vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256,
1387                       c, g->load_dest, g->fniv);
1388         if (some == oprsz) {
1389             break;
1390         }
1391         dofs += some;
1392         aofs += some;
1393         bofs += some;
1394         oprsz -= some;
1395         maxsz -= some;
1396         /* fallthru */
1397     case TCG_TYPE_V128:
1398         expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128,
1399                       c, g->load_dest, g->fniv);
1400         break;
1401     case TCG_TYPE_V64:
1402         expand_3i_vec(g->vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64,
1403                       c, g->load_dest, g->fniv);
1404         break;
1405 
1406     case 0:
1407         if (g->fni8 && check_size_impl(oprsz, 8)) {
1408             expand_3i_i64(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni8);
1409         } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1410             expand_3i_i32(dofs, aofs, bofs, oprsz, c, g->load_dest, g->fni4);
1411         } else {
1412             assert(g->fno != NULL);
1413             tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, c, g->fno);
1414             oprsz = maxsz;
1415         }
1416         break;
1417 
1418     default:
1419         g_assert_not_reached();
1420     }
1421     tcg_swap_vecop_list(hold_list);
1422 
1423     if (oprsz < maxsz) {
1424         expand_clr(dofs + oprsz, maxsz - oprsz);
1425     }
1426 }
1427 
1428 /* Expand a vector four-operand operation.  */
1429 void tcg_gen_gvec_4(uint32_t dofs, uint32_t aofs, uint32_t bofs, uint32_t cofs,
1430                     uint32_t oprsz, uint32_t maxsz, const GVecGen4 *g)
1431 {
1432     const TCGOpcode *this_list = g->opt_opc ? : vecop_list_empty;
1433     const TCGOpcode *hold_list = tcg_swap_vecop_list(this_list);
1434     TCGType type;
1435     uint32_t some;
1436 
1437     check_size_align(oprsz, maxsz, dofs | aofs | bofs | cofs);
1438     check_overlap_4(dofs, aofs, bofs, cofs, maxsz);
1439 
1440     type = 0;
1441     if (g->fniv) {
1442         type = choose_vector_type(g->opt_opc, g->vece, oprsz, g->prefer_i64);
1443     }
1444     switch (type) {
1445     case TCG_TYPE_V256:
1446         /* Recall that ARM SVE allows vector sizes that are not a
1447          * power of 2, but always a multiple of 16.  The intent is
1448          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
1449          */
1450         some = QEMU_ALIGN_DOWN(oprsz, 32);
1451         expand_4_vec(g->vece, dofs, aofs, bofs, cofs, some,
1452                      32, TCG_TYPE_V256, g->write_aofs, g->fniv);
1453         if (some == oprsz) {
1454             break;
1455         }
1456         dofs += some;
1457         aofs += some;
1458         bofs += some;
1459         cofs += some;
1460         oprsz -= some;
1461         maxsz -= some;
1462         /* fallthru */
1463     case TCG_TYPE_V128:
1464         expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz,
1465                      16, TCG_TYPE_V128, g->write_aofs, g->fniv);
1466         break;
1467     case TCG_TYPE_V64:
1468         expand_4_vec(g->vece, dofs, aofs, bofs, cofs, oprsz,
1469                      8, TCG_TYPE_V64, g->write_aofs, g->fniv);
1470         break;
1471 
1472     case 0:
1473         if (g->fni8 && check_size_impl(oprsz, 8)) {
1474             expand_4_i64(dofs, aofs, bofs, cofs, oprsz,
1475                          g->write_aofs, g->fni8);
1476         } else if (g->fni4 && check_size_impl(oprsz, 4)) {
1477             expand_4_i32(dofs, aofs, bofs, cofs, oprsz,
1478                          g->write_aofs, g->fni4);
1479         } else {
1480             assert(g->fno != NULL);
1481             tcg_gen_gvec_4_ool(dofs, aofs, bofs, cofs,
1482                                oprsz, maxsz, g->data, g->fno);
1483             oprsz = maxsz;
1484         }
1485         break;
1486 
1487     default:
1488         g_assert_not_reached();
1489     }
1490     tcg_swap_vecop_list(hold_list);
1491 
1492     if (oprsz < maxsz) {
1493         expand_clr(dofs + oprsz, maxsz - oprsz);
1494     }
1495 }
1496 
1497 /*
1498  * Expand specific vector operations.
1499  */
1500 
1501 static void vec_mov2(unsigned vece, TCGv_vec a, TCGv_vec b)
1502 {
1503     tcg_gen_mov_vec(a, b);
1504 }
1505 
1506 void tcg_gen_gvec_mov(unsigned vece, uint32_t dofs, uint32_t aofs,
1507                       uint32_t oprsz, uint32_t maxsz)
1508 {
1509     static const GVecGen2 g = {
1510         .fni8 = tcg_gen_mov_i64,
1511         .fniv = vec_mov2,
1512         .fno = gen_helper_gvec_mov,
1513         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1514     };
1515     if (dofs != aofs) {
1516         tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g);
1517     } else {
1518         check_size_align(oprsz, maxsz, dofs);
1519         if (oprsz < maxsz) {
1520             expand_clr(dofs + oprsz, maxsz - oprsz);
1521         }
1522     }
1523 }
1524 
1525 void tcg_gen_gvec_dup_i32(unsigned vece, uint32_t dofs, uint32_t oprsz,
1526                           uint32_t maxsz, TCGv_i32 in)
1527 {
1528     check_size_align(oprsz, maxsz, dofs);
1529     tcg_debug_assert(vece <= MO_32);
1530     do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0);
1531 }
1532 
1533 void tcg_gen_gvec_dup_i64(unsigned vece, uint32_t dofs, uint32_t oprsz,
1534                           uint32_t maxsz, TCGv_i64 in)
1535 {
1536     check_size_align(oprsz, maxsz, dofs);
1537     tcg_debug_assert(vece <= MO_64);
1538     do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0);
1539 }
1540 
1541 void tcg_gen_gvec_dup_mem(unsigned vece, uint32_t dofs, uint32_t aofs,
1542                           uint32_t oprsz, uint32_t maxsz)
1543 {
1544     check_size_align(oprsz, maxsz, dofs);
1545     if (vece <= MO_64) {
1546         TCGType type = choose_vector_type(NULL, vece, oprsz, 0);
1547         if (type != 0) {
1548             TCGv_vec t_vec = tcg_temp_new_vec(type);
1549             tcg_gen_dup_mem_vec(vece, t_vec, cpu_env, aofs);
1550             do_dup_store(type, dofs, oprsz, maxsz, t_vec);
1551             tcg_temp_free_vec(t_vec);
1552         } else if (vece <= MO_32) {
1553             TCGv_i32 in = tcg_temp_new_i32();
1554             switch (vece) {
1555             case MO_8:
1556                 tcg_gen_ld8u_i32(in, cpu_env, aofs);
1557                 break;
1558             case MO_16:
1559                 tcg_gen_ld16u_i32(in, cpu_env, aofs);
1560                 break;
1561             default:
1562                 tcg_gen_ld_i32(in, cpu_env, aofs);
1563                 break;
1564             }
1565             do_dup(vece, dofs, oprsz, maxsz, in, NULL, 0);
1566             tcg_temp_free_i32(in);
1567         } else {
1568             TCGv_i64 in = tcg_temp_new_i64();
1569             tcg_gen_ld_i64(in, cpu_env, aofs);
1570             do_dup(vece, dofs, oprsz, maxsz, NULL, in, 0);
1571             tcg_temp_free_i64(in);
1572         }
1573     } else {
1574         /* 128-bit duplicate.  */
1575         /* ??? Dup to 256-bit vector.  */
1576         int i;
1577 
1578         tcg_debug_assert(vece == 4);
1579         tcg_debug_assert(oprsz >= 16);
1580         if (TCG_TARGET_HAS_v128) {
1581             TCGv_vec in = tcg_temp_new_vec(TCG_TYPE_V128);
1582 
1583             tcg_gen_ld_vec(in, cpu_env, aofs);
1584             for (i = 0; i < oprsz; i += 16) {
1585                 tcg_gen_st_vec(in, cpu_env, dofs + i);
1586             }
1587             tcg_temp_free_vec(in);
1588         } else {
1589             TCGv_i64 in0 = tcg_temp_new_i64();
1590             TCGv_i64 in1 = tcg_temp_new_i64();
1591 
1592             tcg_gen_ld_i64(in0, cpu_env, aofs);
1593             tcg_gen_ld_i64(in1, cpu_env, aofs + 8);
1594             for (i = 0; i < oprsz; i += 16) {
1595                 tcg_gen_st_i64(in0, cpu_env, dofs + i);
1596                 tcg_gen_st_i64(in1, cpu_env, dofs + i + 8);
1597             }
1598             tcg_temp_free_i64(in0);
1599             tcg_temp_free_i64(in1);
1600         }
1601         if (oprsz < maxsz) {
1602             expand_clr(dofs + oprsz, maxsz - oprsz);
1603         }
1604     }
1605 }
1606 
1607 void tcg_gen_gvec_dup_imm(unsigned vece, uint32_t dofs, uint32_t oprsz,
1608                           uint32_t maxsz, uint64_t x)
1609 {
1610     check_size_align(oprsz, maxsz, dofs);
1611     do_dup(vece, dofs, oprsz, maxsz, NULL, NULL, x);
1612 }
1613 
1614 void tcg_gen_gvec_not(unsigned vece, uint32_t dofs, uint32_t aofs,
1615                       uint32_t oprsz, uint32_t maxsz)
1616 {
1617     static const GVecGen2 g = {
1618         .fni8 = tcg_gen_not_i64,
1619         .fniv = tcg_gen_not_vec,
1620         .fno = gen_helper_gvec_not,
1621         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1622     };
1623     tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g);
1624 }
1625 
1626 /* Perform a vector addition using normal addition and a mask.  The mask
1627    should be the sign bit of each lane.  This 6-operation form is more
1628    efficient than separate additions when there are 4 or more lanes in
1629    the 64-bit operation.  */
1630 static void gen_addv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m)
1631 {
1632     TCGv_i64 t1 = tcg_temp_new_i64();
1633     TCGv_i64 t2 = tcg_temp_new_i64();
1634     TCGv_i64 t3 = tcg_temp_new_i64();
1635 
1636     tcg_gen_andc_i64(t1, a, m);
1637     tcg_gen_andc_i64(t2, b, m);
1638     tcg_gen_xor_i64(t3, a, b);
1639     tcg_gen_add_i64(d, t1, t2);
1640     tcg_gen_and_i64(t3, t3, m);
1641     tcg_gen_xor_i64(d, d, t3);
1642 
1643     tcg_temp_free_i64(t1);
1644     tcg_temp_free_i64(t2);
1645     tcg_temp_free_i64(t3);
1646 }
1647 
1648 void tcg_gen_vec_add8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1649 {
1650     TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80));
1651     gen_addv_mask(d, a, b, m);
1652     tcg_temp_free_i64(m);
1653 }
1654 
1655 void tcg_gen_vec_add16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1656 {
1657     TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000));
1658     gen_addv_mask(d, a, b, m);
1659     tcg_temp_free_i64(m);
1660 }
1661 
1662 void tcg_gen_vec_add32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1663 {
1664     TCGv_i64 t1 = tcg_temp_new_i64();
1665     TCGv_i64 t2 = tcg_temp_new_i64();
1666 
1667     tcg_gen_andi_i64(t1, a, ~0xffffffffull);
1668     tcg_gen_add_i64(t2, a, b);
1669     tcg_gen_add_i64(t1, t1, b);
1670     tcg_gen_deposit_i64(d, t1, t2, 0, 32);
1671 
1672     tcg_temp_free_i64(t1);
1673     tcg_temp_free_i64(t2);
1674 }
1675 
1676 static const TCGOpcode vecop_list_add[] = { INDEX_op_add_vec, 0 };
1677 
1678 void tcg_gen_gvec_add(unsigned vece, uint32_t dofs, uint32_t aofs,
1679                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1680 {
1681     static const GVecGen3 g[4] = {
1682         { .fni8 = tcg_gen_vec_add8_i64,
1683           .fniv = tcg_gen_add_vec,
1684           .fno = gen_helper_gvec_add8,
1685           .opt_opc = vecop_list_add,
1686           .vece = MO_8 },
1687         { .fni8 = tcg_gen_vec_add16_i64,
1688           .fniv = tcg_gen_add_vec,
1689           .fno = gen_helper_gvec_add16,
1690           .opt_opc = vecop_list_add,
1691           .vece = MO_16 },
1692         { .fni4 = tcg_gen_add_i32,
1693           .fniv = tcg_gen_add_vec,
1694           .fno = gen_helper_gvec_add32,
1695           .opt_opc = vecop_list_add,
1696           .vece = MO_32 },
1697         { .fni8 = tcg_gen_add_i64,
1698           .fniv = tcg_gen_add_vec,
1699           .fno = gen_helper_gvec_add64,
1700           .opt_opc = vecop_list_add,
1701           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1702           .vece = MO_64 },
1703     };
1704 
1705     tcg_debug_assert(vece <= MO_64);
1706     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
1707 }
1708 
1709 void tcg_gen_gvec_adds(unsigned vece, uint32_t dofs, uint32_t aofs,
1710                        TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
1711 {
1712     static const GVecGen2s g[4] = {
1713         { .fni8 = tcg_gen_vec_add8_i64,
1714           .fniv = tcg_gen_add_vec,
1715           .fno = gen_helper_gvec_adds8,
1716           .opt_opc = vecop_list_add,
1717           .vece = MO_8 },
1718         { .fni8 = tcg_gen_vec_add16_i64,
1719           .fniv = tcg_gen_add_vec,
1720           .fno = gen_helper_gvec_adds16,
1721           .opt_opc = vecop_list_add,
1722           .vece = MO_16 },
1723         { .fni4 = tcg_gen_add_i32,
1724           .fniv = tcg_gen_add_vec,
1725           .fno = gen_helper_gvec_adds32,
1726           .opt_opc = vecop_list_add,
1727           .vece = MO_32 },
1728         { .fni8 = tcg_gen_add_i64,
1729           .fniv = tcg_gen_add_vec,
1730           .fno = gen_helper_gvec_adds64,
1731           .opt_opc = vecop_list_add,
1732           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1733           .vece = MO_64 },
1734     };
1735 
1736     tcg_debug_assert(vece <= MO_64);
1737     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
1738 }
1739 
1740 void tcg_gen_gvec_addi(unsigned vece, uint32_t dofs, uint32_t aofs,
1741                        int64_t c, uint32_t oprsz, uint32_t maxsz)
1742 {
1743     TCGv_i64 tmp = tcg_const_i64(c);
1744     tcg_gen_gvec_adds(vece, dofs, aofs, tmp, oprsz, maxsz);
1745     tcg_temp_free_i64(tmp);
1746 }
1747 
1748 static const TCGOpcode vecop_list_sub[] = { INDEX_op_sub_vec, 0 };
1749 
1750 void tcg_gen_gvec_subs(unsigned vece, uint32_t dofs, uint32_t aofs,
1751                        TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
1752 {
1753     static const GVecGen2s g[4] = {
1754         { .fni8 = tcg_gen_vec_sub8_i64,
1755           .fniv = tcg_gen_sub_vec,
1756           .fno = gen_helper_gvec_subs8,
1757           .opt_opc = vecop_list_sub,
1758           .vece = MO_8 },
1759         { .fni8 = tcg_gen_vec_sub16_i64,
1760           .fniv = tcg_gen_sub_vec,
1761           .fno = gen_helper_gvec_subs16,
1762           .opt_opc = vecop_list_sub,
1763           .vece = MO_16 },
1764         { .fni4 = tcg_gen_sub_i32,
1765           .fniv = tcg_gen_sub_vec,
1766           .fno = gen_helper_gvec_subs32,
1767           .opt_opc = vecop_list_sub,
1768           .vece = MO_32 },
1769         { .fni8 = tcg_gen_sub_i64,
1770           .fniv = tcg_gen_sub_vec,
1771           .fno = gen_helper_gvec_subs64,
1772           .opt_opc = vecop_list_sub,
1773           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1774           .vece = MO_64 },
1775     };
1776 
1777     tcg_debug_assert(vece <= MO_64);
1778     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
1779 }
1780 
1781 /* Perform a vector subtraction using normal subtraction and a mask.
1782    Compare gen_addv_mask above.  */
1783 static void gen_subv_mask(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 m)
1784 {
1785     TCGv_i64 t1 = tcg_temp_new_i64();
1786     TCGv_i64 t2 = tcg_temp_new_i64();
1787     TCGv_i64 t3 = tcg_temp_new_i64();
1788 
1789     tcg_gen_or_i64(t1, a, m);
1790     tcg_gen_andc_i64(t2, b, m);
1791     tcg_gen_eqv_i64(t3, a, b);
1792     tcg_gen_sub_i64(d, t1, t2);
1793     tcg_gen_and_i64(t3, t3, m);
1794     tcg_gen_xor_i64(d, d, t3);
1795 
1796     tcg_temp_free_i64(t1);
1797     tcg_temp_free_i64(t2);
1798     tcg_temp_free_i64(t3);
1799 }
1800 
1801 void tcg_gen_vec_sub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1802 {
1803     TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80));
1804     gen_subv_mask(d, a, b, m);
1805     tcg_temp_free_i64(m);
1806 }
1807 
1808 void tcg_gen_vec_sub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1809 {
1810     TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000));
1811     gen_subv_mask(d, a, b, m);
1812     tcg_temp_free_i64(m);
1813 }
1814 
1815 void tcg_gen_vec_sub32_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1816 {
1817     TCGv_i64 t1 = tcg_temp_new_i64();
1818     TCGv_i64 t2 = tcg_temp_new_i64();
1819 
1820     tcg_gen_andi_i64(t1, b, ~0xffffffffull);
1821     tcg_gen_sub_i64(t2, a, b);
1822     tcg_gen_sub_i64(t1, a, t1);
1823     tcg_gen_deposit_i64(d, t1, t2, 0, 32);
1824 
1825     tcg_temp_free_i64(t1);
1826     tcg_temp_free_i64(t2);
1827 }
1828 
1829 void tcg_gen_gvec_sub(unsigned vece, uint32_t dofs, uint32_t aofs,
1830                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1831 {
1832     static const GVecGen3 g[4] = {
1833         { .fni8 = tcg_gen_vec_sub8_i64,
1834           .fniv = tcg_gen_sub_vec,
1835           .fno = gen_helper_gvec_sub8,
1836           .opt_opc = vecop_list_sub,
1837           .vece = MO_8 },
1838         { .fni8 = tcg_gen_vec_sub16_i64,
1839           .fniv = tcg_gen_sub_vec,
1840           .fno = gen_helper_gvec_sub16,
1841           .opt_opc = vecop_list_sub,
1842           .vece = MO_16 },
1843         { .fni4 = tcg_gen_sub_i32,
1844           .fniv = tcg_gen_sub_vec,
1845           .fno = gen_helper_gvec_sub32,
1846           .opt_opc = vecop_list_sub,
1847           .vece = MO_32 },
1848         { .fni8 = tcg_gen_sub_i64,
1849           .fniv = tcg_gen_sub_vec,
1850           .fno = gen_helper_gvec_sub64,
1851           .opt_opc = vecop_list_sub,
1852           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1853           .vece = MO_64 },
1854     };
1855 
1856     tcg_debug_assert(vece <= MO_64);
1857     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
1858 }
1859 
1860 static const TCGOpcode vecop_list_mul[] = { INDEX_op_mul_vec, 0 };
1861 
1862 void tcg_gen_gvec_mul(unsigned vece, uint32_t dofs, uint32_t aofs,
1863                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1864 {
1865     static const GVecGen3 g[4] = {
1866         { .fniv = tcg_gen_mul_vec,
1867           .fno = gen_helper_gvec_mul8,
1868           .opt_opc = vecop_list_mul,
1869           .vece = MO_8 },
1870         { .fniv = tcg_gen_mul_vec,
1871           .fno = gen_helper_gvec_mul16,
1872           .opt_opc = vecop_list_mul,
1873           .vece = MO_16 },
1874         { .fni4 = tcg_gen_mul_i32,
1875           .fniv = tcg_gen_mul_vec,
1876           .fno = gen_helper_gvec_mul32,
1877           .opt_opc = vecop_list_mul,
1878           .vece = MO_32 },
1879         { .fni8 = tcg_gen_mul_i64,
1880           .fniv = tcg_gen_mul_vec,
1881           .fno = gen_helper_gvec_mul64,
1882           .opt_opc = vecop_list_mul,
1883           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1884           .vece = MO_64 },
1885     };
1886 
1887     tcg_debug_assert(vece <= MO_64);
1888     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
1889 }
1890 
1891 void tcg_gen_gvec_muls(unsigned vece, uint32_t dofs, uint32_t aofs,
1892                        TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
1893 {
1894     static const GVecGen2s g[4] = {
1895         { .fniv = tcg_gen_mul_vec,
1896           .fno = gen_helper_gvec_muls8,
1897           .opt_opc = vecop_list_mul,
1898           .vece = MO_8 },
1899         { .fniv = tcg_gen_mul_vec,
1900           .fno = gen_helper_gvec_muls16,
1901           .opt_opc = vecop_list_mul,
1902           .vece = MO_16 },
1903         { .fni4 = tcg_gen_mul_i32,
1904           .fniv = tcg_gen_mul_vec,
1905           .fno = gen_helper_gvec_muls32,
1906           .opt_opc = vecop_list_mul,
1907           .vece = MO_32 },
1908         { .fni8 = tcg_gen_mul_i64,
1909           .fniv = tcg_gen_mul_vec,
1910           .fno = gen_helper_gvec_muls64,
1911           .opt_opc = vecop_list_mul,
1912           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1913           .vece = MO_64 },
1914     };
1915 
1916     tcg_debug_assert(vece <= MO_64);
1917     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &g[vece]);
1918 }
1919 
1920 void tcg_gen_gvec_muli(unsigned vece, uint32_t dofs, uint32_t aofs,
1921                        int64_t c, uint32_t oprsz, uint32_t maxsz)
1922 {
1923     TCGv_i64 tmp = tcg_const_i64(c);
1924     tcg_gen_gvec_muls(vece, dofs, aofs, tmp, oprsz, maxsz);
1925     tcg_temp_free_i64(tmp);
1926 }
1927 
1928 void tcg_gen_gvec_ssadd(unsigned vece, uint32_t dofs, uint32_t aofs,
1929                         uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1930 {
1931     static const TCGOpcode vecop_list[] = { INDEX_op_ssadd_vec, 0 };
1932     static const GVecGen3 g[4] = {
1933         { .fniv = tcg_gen_ssadd_vec,
1934           .fno = gen_helper_gvec_ssadd8,
1935           .opt_opc = vecop_list,
1936           .vece = MO_8 },
1937         { .fniv = tcg_gen_ssadd_vec,
1938           .fno = gen_helper_gvec_ssadd16,
1939           .opt_opc = vecop_list,
1940           .vece = MO_16 },
1941         { .fniv = tcg_gen_ssadd_vec,
1942           .fno = gen_helper_gvec_ssadd32,
1943           .opt_opc = vecop_list,
1944           .vece = MO_32 },
1945         { .fniv = tcg_gen_ssadd_vec,
1946           .fno = gen_helper_gvec_ssadd64,
1947           .opt_opc = vecop_list,
1948           .vece = MO_64 },
1949     };
1950     tcg_debug_assert(vece <= MO_64);
1951     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
1952 }
1953 
1954 void tcg_gen_gvec_sssub(unsigned vece, uint32_t dofs, uint32_t aofs,
1955                         uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1956 {
1957     static const TCGOpcode vecop_list[] = { INDEX_op_sssub_vec, 0 };
1958     static const GVecGen3 g[4] = {
1959         { .fniv = tcg_gen_sssub_vec,
1960           .fno = gen_helper_gvec_sssub8,
1961           .opt_opc = vecop_list,
1962           .vece = MO_8 },
1963         { .fniv = tcg_gen_sssub_vec,
1964           .fno = gen_helper_gvec_sssub16,
1965           .opt_opc = vecop_list,
1966           .vece = MO_16 },
1967         { .fniv = tcg_gen_sssub_vec,
1968           .fno = gen_helper_gvec_sssub32,
1969           .opt_opc = vecop_list,
1970           .vece = MO_32 },
1971         { .fniv = tcg_gen_sssub_vec,
1972           .fno = gen_helper_gvec_sssub64,
1973           .opt_opc = vecop_list,
1974           .vece = MO_64 },
1975     };
1976     tcg_debug_assert(vece <= MO_64);
1977     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
1978 }
1979 
1980 static void tcg_gen_usadd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
1981 {
1982     TCGv_i32 max = tcg_const_i32(-1);
1983     tcg_gen_add_i32(d, a, b);
1984     tcg_gen_movcond_i32(TCG_COND_LTU, d, d, a, max, d);
1985     tcg_temp_free_i32(max);
1986 }
1987 
1988 static void tcg_gen_usadd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1989 {
1990     TCGv_i64 max = tcg_const_i64(-1);
1991     tcg_gen_add_i64(d, a, b);
1992     tcg_gen_movcond_i64(TCG_COND_LTU, d, d, a, max, d);
1993     tcg_temp_free_i64(max);
1994 }
1995 
1996 void tcg_gen_gvec_usadd(unsigned vece, uint32_t dofs, uint32_t aofs,
1997                         uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
1998 {
1999     static const TCGOpcode vecop_list[] = { INDEX_op_usadd_vec, 0 };
2000     static const GVecGen3 g[4] = {
2001         { .fniv = tcg_gen_usadd_vec,
2002           .fno = gen_helper_gvec_usadd8,
2003           .opt_opc = vecop_list,
2004           .vece = MO_8 },
2005         { .fniv = tcg_gen_usadd_vec,
2006           .fno = gen_helper_gvec_usadd16,
2007           .opt_opc = vecop_list,
2008           .vece = MO_16 },
2009         { .fni4 = tcg_gen_usadd_i32,
2010           .fniv = tcg_gen_usadd_vec,
2011           .fno = gen_helper_gvec_usadd32,
2012           .opt_opc = vecop_list,
2013           .vece = MO_32 },
2014         { .fni8 = tcg_gen_usadd_i64,
2015           .fniv = tcg_gen_usadd_vec,
2016           .fno = gen_helper_gvec_usadd64,
2017           .opt_opc = vecop_list,
2018           .vece = MO_64 }
2019     };
2020     tcg_debug_assert(vece <= MO_64);
2021     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2022 }
2023 
2024 static void tcg_gen_ussub_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
2025 {
2026     TCGv_i32 min = tcg_const_i32(0);
2027     tcg_gen_sub_i32(d, a, b);
2028     tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, min, d);
2029     tcg_temp_free_i32(min);
2030 }
2031 
2032 static void tcg_gen_ussub_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
2033 {
2034     TCGv_i64 min = tcg_const_i64(0);
2035     tcg_gen_sub_i64(d, a, b);
2036     tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, min, d);
2037     tcg_temp_free_i64(min);
2038 }
2039 
2040 void tcg_gen_gvec_ussub(unsigned vece, uint32_t dofs, uint32_t aofs,
2041                         uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2042 {
2043     static const TCGOpcode vecop_list[] = { INDEX_op_ussub_vec, 0 };
2044     static const GVecGen3 g[4] = {
2045         { .fniv = tcg_gen_ussub_vec,
2046           .fno = gen_helper_gvec_ussub8,
2047           .opt_opc = vecop_list,
2048           .vece = MO_8 },
2049         { .fniv = tcg_gen_ussub_vec,
2050           .fno = gen_helper_gvec_ussub16,
2051           .opt_opc = vecop_list,
2052           .vece = MO_16 },
2053         { .fni4 = tcg_gen_ussub_i32,
2054           .fniv = tcg_gen_ussub_vec,
2055           .fno = gen_helper_gvec_ussub32,
2056           .opt_opc = vecop_list,
2057           .vece = MO_32 },
2058         { .fni8 = tcg_gen_ussub_i64,
2059           .fniv = tcg_gen_ussub_vec,
2060           .fno = gen_helper_gvec_ussub64,
2061           .opt_opc = vecop_list,
2062           .vece = MO_64 }
2063     };
2064     tcg_debug_assert(vece <= MO_64);
2065     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2066 }
2067 
2068 void tcg_gen_gvec_smin(unsigned vece, uint32_t dofs, uint32_t aofs,
2069                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2070 {
2071     static const TCGOpcode vecop_list[] = { INDEX_op_smin_vec, 0 };
2072     static const GVecGen3 g[4] = {
2073         { .fniv = tcg_gen_smin_vec,
2074           .fno = gen_helper_gvec_smin8,
2075           .opt_opc = vecop_list,
2076           .vece = MO_8 },
2077         { .fniv = tcg_gen_smin_vec,
2078           .fno = gen_helper_gvec_smin16,
2079           .opt_opc = vecop_list,
2080           .vece = MO_16 },
2081         { .fni4 = tcg_gen_smin_i32,
2082           .fniv = tcg_gen_smin_vec,
2083           .fno = gen_helper_gvec_smin32,
2084           .opt_opc = vecop_list,
2085           .vece = MO_32 },
2086         { .fni8 = tcg_gen_smin_i64,
2087           .fniv = tcg_gen_smin_vec,
2088           .fno = gen_helper_gvec_smin64,
2089           .opt_opc = vecop_list,
2090           .vece = MO_64 }
2091     };
2092     tcg_debug_assert(vece <= MO_64);
2093     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2094 }
2095 
2096 void tcg_gen_gvec_umin(unsigned vece, uint32_t dofs, uint32_t aofs,
2097                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2098 {
2099     static const TCGOpcode vecop_list[] = { INDEX_op_umin_vec, 0 };
2100     static const GVecGen3 g[4] = {
2101         { .fniv = tcg_gen_umin_vec,
2102           .fno = gen_helper_gvec_umin8,
2103           .opt_opc = vecop_list,
2104           .vece = MO_8 },
2105         { .fniv = tcg_gen_umin_vec,
2106           .fno = gen_helper_gvec_umin16,
2107           .opt_opc = vecop_list,
2108           .vece = MO_16 },
2109         { .fni4 = tcg_gen_umin_i32,
2110           .fniv = tcg_gen_umin_vec,
2111           .fno = gen_helper_gvec_umin32,
2112           .opt_opc = vecop_list,
2113           .vece = MO_32 },
2114         { .fni8 = tcg_gen_umin_i64,
2115           .fniv = tcg_gen_umin_vec,
2116           .fno = gen_helper_gvec_umin64,
2117           .opt_opc = vecop_list,
2118           .vece = MO_64 }
2119     };
2120     tcg_debug_assert(vece <= MO_64);
2121     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2122 }
2123 
2124 void tcg_gen_gvec_smax(unsigned vece, uint32_t dofs, uint32_t aofs,
2125                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2126 {
2127     static const TCGOpcode vecop_list[] = { INDEX_op_smax_vec, 0 };
2128     static const GVecGen3 g[4] = {
2129         { .fniv = tcg_gen_smax_vec,
2130           .fno = gen_helper_gvec_smax8,
2131           .opt_opc = vecop_list,
2132           .vece = MO_8 },
2133         { .fniv = tcg_gen_smax_vec,
2134           .fno = gen_helper_gvec_smax16,
2135           .opt_opc = vecop_list,
2136           .vece = MO_16 },
2137         { .fni4 = tcg_gen_smax_i32,
2138           .fniv = tcg_gen_smax_vec,
2139           .fno = gen_helper_gvec_smax32,
2140           .opt_opc = vecop_list,
2141           .vece = MO_32 },
2142         { .fni8 = tcg_gen_smax_i64,
2143           .fniv = tcg_gen_smax_vec,
2144           .fno = gen_helper_gvec_smax64,
2145           .opt_opc = vecop_list,
2146           .vece = MO_64 }
2147     };
2148     tcg_debug_assert(vece <= MO_64);
2149     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2150 }
2151 
2152 void tcg_gen_gvec_umax(unsigned vece, uint32_t dofs, uint32_t aofs,
2153                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2154 {
2155     static const TCGOpcode vecop_list[] = { INDEX_op_umax_vec, 0 };
2156     static const GVecGen3 g[4] = {
2157         { .fniv = tcg_gen_umax_vec,
2158           .fno = gen_helper_gvec_umax8,
2159           .opt_opc = vecop_list,
2160           .vece = MO_8 },
2161         { .fniv = tcg_gen_umax_vec,
2162           .fno = gen_helper_gvec_umax16,
2163           .opt_opc = vecop_list,
2164           .vece = MO_16 },
2165         { .fni4 = tcg_gen_umax_i32,
2166           .fniv = tcg_gen_umax_vec,
2167           .fno = gen_helper_gvec_umax32,
2168           .opt_opc = vecop_list,
2169           .vece = MO_32 },
2170         { .fni8 = tcg_gen_umax_i64,
2171           .fniv = tcg_gen_umax_vec,
2172           .fno = gen_helper_gvec_umax64,
2173           .opt_opc = vecop_list,
2174           .vece = MO_64 }
2175     };
2176     tcg_debug_assert(vece <= MO_64);
2177     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2178 }
2179 
2180 /* Perform a vector negation using normal negation and a mask.
2181    Compare gen_subv_mask above.  */
2182 static void gen_negv_mask(TCGv_i64 d, TCGv_i64 b, TCGv_i64 m)
2183 {
2184     TCGv_i64 t2 = tcg_temp_new_i64();
2185     TCGv_i64 t3 = tcg_temp_new_i64();
2186 
2187     tcg_gen_andc_i64(t3, m, b);
2188     tcg_gen_andc_i64(t2, b, m);
2189     tcg_gen_sub_i64(d, m, t2);
2190     tcg_gen_xor_i64(d, d, t3);
2191 
2192     tcg_temp_free_i64(t2);
2193     tcg_temp_free_i64(t3);
2194 }
2195 
2196 void tcg_gen_vec_neg8_i64(TCGv_i64 d, TCGv_i64 b)
2197 {
2198     TCGv_i64 m = tcg_const_i64(dup_const(MO_8, 0x80));
2199     gen_negv_mask(d, b, m);
2200     tcg_temp_free_i64(m);
2201 }
2202 
2203 void tcg_gen_vec_neg16_i64(TCGv_i64 d, TCGv_i64 b)
2204 {
2205     TCGv_i64 m = tcg_const_i64(dup_const(MO_16, 0x8000));
2206     gen_negv_mask(d, b, m);
2207     tcg_temp_free_i64(m);
2208 }
2209 
2210 void tcg_gen_vec_neg32_i64(TCGv_i64 d, TCGv_i64 b)
2211 {
2212     TCGv_i64 t1 = tcg_temp_new_i64();
2213     TCGv_i64 t2 = tcg_temp_new_i64();
2214 
2215     tcg_gen_andi_i64(t1, b, ~0xffffffffull);
2216     tcg_gen_neg_i64(t2, b);
2217     tcg_gen_neg_i64(t1, t1);
2218     tcg_gen_deposit_i64(d, t1, t2, 0, 32);
2219 
2220     tcg_temp_free_i64(t1);
2221     tcg_temp_free_i64(t2);
2222 }
2223 
2224 void tcg_gen_gvec_neg(unsigned vece, uint32_t dofs, uint32_t aofs,
2225                       uint32_t oprsz, uint32_t maxsz)
2226 {
2227     static const TCGOpcode vecop_list[] = { INDEX_op_neg_vec, 0 };
2228     static const GVecGen2 g[4] = {
2229         { .fni8 = tcg_gen_vec_neg8_i64,
2230           .fniv = tcg_gen_neg_vec,
2231           .fno = gen_helper_gvec_neg8,
2232           .opt_opc = vecop_list,
2233           .vece = MO_8 },
2234         { .fni8 = tcg_gen_vec_neg16_i64,
2235           .fniv = tcg_gen_neg_vec,
2236           .fno = gen_helper_gvec_neg16,
2237           .opt_opc = vecop_list,
2238           .vece = MO_16 },
2239         { .fni4 = tcg_gen_neg_i32,
2240           .fniv = tcg_gen_neg_vec,
2241           .fno = gen_helper_gvec_neg32,
2242           .opt_opc = vecop_list,
2243           .vece = MO_32 },
2244         { .fni8 = tcg_gen_neg_i64,
2245           .fniv = tcg_gen_neg_vec,
2246           .fno = gen_helper_gvec_neg64,
2247           .opt_opc = vecop_list,
2248           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2249           .vece = MO_64 },
2250     };
2251 
2252     tcg_debug_assert(vece <= MO_64);
2253     tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]);
2254 }
2255 
2256 static void gen_absv_mask(TCGv_i64 d, TCGv_i64 b, unsigned vece)
2257 {
2258     TCGv_i64 t = tcg_temp_new_i64();
2259     int nbit = 8 << vece;
2260 
2261     /* Create -1 for each negative element.  */
2262     tcg_gen_shri_i64(t, b, nbit - 1);
2263     tcg_gen_andi_i64(t, t, dup_const(vece, 1));
2264     tcg_gen_muli_i64(t, t, (1 << nbit) - 1);
2265 
2266     /*
2267      * Invert (via xor -1) and add one (via sub -1).
2268      * Because of the ordering the msb is cleared,
2269      * so we never have carry into the next element.
2270      */
2271     tcg_gen_xor_i64(d, b, t);
2272     tcg_gen_sub_i64(d, d, t);
2273 
2274     tcg_temp_free_i64(t);
2275 }
2276 
2277 static void tcg_gen_vec_abs8_i64(TCGv_i64 d, TCGv_i64 b)
2278 {
2279     gen_absv_mask(d, b, MO_8);
2280 }
2281 
2282 static void tcg_gen_vec_abs16_i64(TCGv_i64 d, TCGv_i64 b)
2283 {
2284     gen_absv_mask(d, b, MO_16);
2285 }
2286 
2287 void tcg_gen_gvec_abs(unsigned vece, uint32_t dofs, uint32_t aofs,
2288                       uint32_t oprsz, uint32_t maxsz)
2289 {
2290     static const TCGOpcode vecop_list[] = { INDEX_op_abs_vec, 0 };
2291     static const GVecGen2 g[4] = {
2292         { .fni8 = tcg_gen_vec_abs8_i64,
2293           .fniv = tcg_gen_abs_vec,
2294           .fno = gen_helper_gvec_abs8,
2295           .opt_opc = vecop_list,
2296           .vece = MO_8 },
2297         { .fni8 = tcg_gen_vec_abs16_i64,
2298           .fniv = tcg_gen_abs_vec,
2299           .fno = gen_helper_gvec_abs16,
2300           .opt_opc = vecop_list,
2301           .vece = MO_16 },
2302         { .fni4 = tcg_gen_abs_i32,
2303           .fniv = tcg_gen_abs_vec,
2304           .fno = gen_helper_gvec_abs32,
2305           .opt_opc = vecop_list,
2306           .vece = MO_32 },
2307         { .fni8 = tcg_gen_abs_i64,
2308           .fniv = tcg_gen_abs_vec,
2309           .fno = gen_helper_gvec_abs64,
2310           .opt_opc = vecop_list,
2311           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2312           .vece = MO_64 },
2313     };
2314 
2315     tcg_debug_assert(vece <= MO_64);
2316     tcg_gen_gvec_2(dofs, aofs, oprsz, maxsz, &g[vece]);
2317 }
2318 
2319 void tcg_gen_gvec_and(unsigned vece, uint32_t dofs, uint32_t aofs,
2320                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2321 {
2322     static const GVecGen3 g = {
2323         .fni8 = tcg_gen_and_i64,
2324         .fniv = tcg_gen_and_vec,
2325         .fno = gen_helper_gvec_and,
2326         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2327     };
2328 
2329     if (aofs == bofs) {
2330         tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
2331     } else {
2332         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2333     }
2334 }
2335 
2336 void tcg_gen_gvec_or(unsigned vece, uint32_t dofs, uint32_t aofs,
2337                      uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2338 {
2339     static const GVecGen3 g = {
2340         .fni8 = tcg_gen_or_i64,
2341         .fniv = tcg_gen_or_vec,
2342         .fno = gen_helper_gvec_or,
2343         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2344     };
2345 
2346     if (aofs == bofs) {
2347         tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
2348     } else {
2349         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2350     }
2351 }
2352 
2353 void tcg_gen_gvec_xor(unsigned vece, uint32_t dofs, uint32_t aofs,
2354                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2355 {
2356     static const GVecGen3 g = {
2357         .fni8 = tcg_gen_xor_i64,
2358         .fniv = tcg_gen_xor_vec,
2359         .fno = gen_helper_gvec_xor,
2360         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2361     };
2362 
2363     if (aofs == bofs) {
2364         tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0);
2365     } else {
2366         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2367     }
2368 }
2369 
2370 void tcg_gen_gvec_andc(unsigned vece, uint32_t dofs, uint32_t aofs,
2371                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2372 {
2373     static const GVecGen3 g = {
2374         .fni8 = tcg_gen_andc_i64,
2375         .fniv = tcg_gen_andc_vec,
2376         .fno = gen_helper_gvec_andc,
2377         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2378     };
2379 
2380     if (aofs == bofs) {
2381         tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, 0);
2382     } else {
2383         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2384     }
2385 }
2386 
2387 void tcg_gen_gvec_orc(unsigned vece, uint32_t dofs, uint32_t aofs,
2388                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2389 {
2390     static const GVecGen3 g = {
2391         .fni8 = tcg_gen_orc_i64,
2392         .fniv = tcg_gen_orc_vec,
2393         .fno = gen_helper_gvec_orc,
2394         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2395     };
2396 
2397     if (aofs == bofs) {
2398         tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1);
2399     } else {
2400         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2401     }
2402 }
2403 
2404 void tcg_gen_gvec_nand(unsigned vece, uint32_t dofs, uint32_t aofs,
2405                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2406 {
2407     static const GVecGen3 g = {
2408         .fni8 = tcg_gen_nand_i64,
2409         .fniv = tcg_gen_nand_vec,
2410         .fno = gen_helper_gvec_nand,
2411         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2412     };
2413 
2414     if (aofs == bofs) {
2415         tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz);
2416     } else {
2417         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2418     }
2419 }
2420 
2421 void tcg_gen_gvec_nor(unsigned vece, uint32_t dofs, uint32_t aofs,
2422                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2423 {
2424     static const GVecGen3 g = {
2425         .fni8 = tcg_gen_nor_i64,
2426         .fniv = tcg_gen_nor_vec,
2427         .fno = gen_helper_gvec_nor,
2428         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2429     };
2430 
2431     if (aofs == bofs) {
2432         tcg_gen_gvec_not(vece, dofs, aofs, oprsz, maxsz);
2433     } else {
2434         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2435     }
2436 }
2437 
2438 void tcg_gen_gvec_eqv(unsigned vece, uint32_t dofs, uint32_t aofs,
2439                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2440 {
2441     static const GVecGen3 g = {
2442         .fni8 = tcg_gen_eqv_i64,
2443         .fniv = tcg_gen_eqv_vec,
2444         .fno = gen_helper_gvec_eqv,
2445         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2446     };
2447 
2448     if (aofs == bofs) {
2449         tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, -1);
2450     } else {
2451         tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g);
2452     }
2453 }
2454 
2455 static const GVecGen2s gop_ands = {
2456     .fni8 = tcg_gen_and_i64,
2457     .fniv = tcg_gen_and_vec,
2458     .fno = gen_helper_gvec_ands,
2459     .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2460     .vece = MO_64
2461 };
2462 
2463 void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
2464                        TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
2465 {
2466     TCGv_i64 tmp = tcg_temp_new_i64();
2467     gen_dup_i64(vece, tmp, c);
2468     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
2469     tcg_temp_free_i64(tmp);
2470 }
2471 
2472 void tcg_gen_gvec_andi(unsigned vece, uint32_t dofs, uint32_t aofs,
2473                        int64_t c, uint32_t oprsz, uint32_t maxsz)
2474 {
2475     TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
2476     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
2477     tcg_temp_free_i64(tmp);
2478 }
2479 
2480 static const GVecGen2s gop_xors = {
2481     .fni8 = tcg_gen_xor_i64,
2482     .fniv = tcg_gen_xor_vec,
2483     .fno = gen_helper_gvec_xors,
2484     .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2485     .vece = MO_64
2486 };
2487 
2488 void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
2489                        TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
2490 {
2491     TCGv_i64 tmp = tcg_temp_new_i64();
2492     gen_dup_i64(vece, tmp, c);
2493     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
2494     tcg_temp_free_i64(tmp);
2495 }
2496 
2497 void tcg_gen_gvec_xori(unsigned vece, uint32_t dofs, uint32_t aofs,
2498                        int64_t c, uint32_t oprsz, uint32_t maxsz)
2499 {
2500     TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
2501     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
2502     tcg_temp_free_i64(tmp);
2503 }
2504 
2505 static const GVecGen2s gop_ors = {
2506     .fni8 = tcg_gen_or_i64,
2507     .fniv = tcg_gen_or_vec,
2508     .fno = gen_helper_gvec_ors,
2509     .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2510     .vece = MO_64
2511 };
2512 
2513 void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
2514                       TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
2515 {
2516     TCGv_i64 tmp = tcg_temp_new_i64();
2517     gen_dup_i64(vece, tmp, c);
2518     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
2519     tcg_temp_free_i64(tmp);
2520 }
2521 
2522 void tcg_gen_gvec_ori(unsigned vece, uint32_t dofs, uint32_t aofs,
2523                       int64_t c, uint32_t oprsz, uint32_t maxsz)
2524 {
2525     TCGv_i64 tmp = tcg_const_i64(dup_const(vece, c));
2526     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
2527     tcg_temp_free_i64(tmp);
2528 }
2529 
2530 void tcg_gen_vec_shl8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2531 {
2532     uint64_t mask = dup_const(MO_8, 0xff << c);
2533     tcg_gen_shli_i64(d, a, c);
2534     tcg_gen_andi_i64(d, d, mask);
2535 }
2536 
2537 void tcg_gen_vec_shl16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2538 {
2539     uint64_t mask = dup_const(MO_16, 0xffff << c);
2540     tcg_gen_shli_i64(d, a, c);
2541     tcg_gen_andi_i64(d, d, mask);
2542 }
2543 
2544 void tcg_gen_gvec_shli(unsigned vece, uint32_t dofs, uint32_t aofs,
2545                        int64_t shift, uint32_t oprsz, uint32_t maxsz)
2546 {
2547     static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
2548     static const GVecGen2i g[4] = {
2549         { .fni8 = tcg_gen_vec_shl8i_i64,
2550           .fniv = tcg_gen_shli_vec,
2551           .fno = gen_helper_gvec_shl8i,
2552           .opt_opc = vecop_list,
2553           .vece = MO_8 },
2554         { .fni8 = tcg_gen_vec_shl16i_i64,
2555           .fniv = tcg_gen_shli_vec,
2556           .fno = gen_helper_gvec_shl16i,
2557           .opt_opc = vecop_list,
2558           .vece = MO_16 },
2559         { .fni4 = tcg_gen_shli_i32,
2560           .fniv = tcg_gen_shli_vec,
2561           .fno = gen_helper_gvec_shl32i,
2562           .opt_opc = vecop_list,
2563           .vece = MO_32 },
2564         { .fni8 = tcg_gen_shli_i64,
2565           .fniv = tcg_gen_shli_vec,
2566           .fno = gen_helper_gvec_shl64i,
2567           .opt_opc = vecop_list,
2568           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2569           .vece = MO_64 },
2570     };
2571 
2572     tcg_debug_assert(vece <= MO_64);
2573     tcg_debug_assert(shift >= 0 && shift < (8 << vece));
2574     if (shift == 0) {
2575         tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
2576     } else {
2577         tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]);
2578     }
2579 }
2580 
2581 void tcg_gen_vec_shr8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2582 {
2583     uint64_t mask = dup_const(MO_8, 0xff >> c);
2584     tcg_gen_shri_i64(d, a, c);
2585     tcg_gen_andi_i64(d, d, mask);
2586 }
2587 
2588 void tcg_gen_vec_shr16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2589 {
2590     uint64_t mask = dup_const(MO_16, 0xffff >> c);
2591     tcg_gen_shri_i64(d, a, c);
2592     tcg_gen_andi_i64(d, d, mask);
2593 }
2594 
2595 void tcg_gen_gvec_shri(unsigned vece, uint32_t dofs, uint32_t aofs,
2596                        int64_t shift, uint32_t oprsz, uint32_t maxsz)
2597 {
2598     static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
2599     static const GVecGen2i g[4] = {
2600         { .fni8 = tcg_gen_vec_shr8i_i64,
2601           .fniv = tcg_gen_shri_vec,
2602           .fno = gen_helper_gvec_shr8i,
2603           .opt_opc = vecop_list,
2604           .vece = MO_8 },
2605         { .fni8 = tcg_gen_vec_shr16i_i64,
2606           .fniv = tcg_gen_shri_vec,
2607           .fno = gen_helper_gvec_shr16i,
2608           .opt_opc = vecop_list,
2609           .vece = MO_16 },
2610         { .fni4 = tcg_gen_shri_i32,
2611           .fniv = tcg_gen_shri_vec,
2612           .fno = gen_helper_gvec_shr32i,
2613           .opt_opc = vecop_list,
2614           .vece = MO_32 },
2615         { .fni8 = tcg_gen_shri_i64,
2616           .fniv = tcg_gen_shri_vec,
2617           .fno = gen_helper_gvec_shr64i,
2618           .opt_opc = vecop_list,
2619           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2620           .vece = MO_64 },
2621     };
2622 
2623     tcg_debug_assert(vece <= MO_64);
2624     tcg_debug_assert(shift >= 0 && shift < (8 << vece));
2625     if (shift == 0) {
2626         tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
2627     } else {
2628         tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]);
2629     }
2630 }
2631 
2632 void tcg_gen_vec_sar8i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2633 {
2634     uint64_t s_mask = dup_const(MO_8, 0x80 >> c);
2635     uint64_t c_mask = dup_const(MO_8, 0xff >> c);
2636     TCGv_i64 s = tcg_temp_new_i64();
2637 
2638     tcg_gen_shri_i64(d, a, c);
2639     tcg_gen_andi_i64(s, d, s_mask);  /* isolate (shifted) sign bit */
2640     tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */
2641     tcg_gen_andi_i64(d, d, c_mask);  /* clear out bits above sign  */
2642     tcg_gen_or_i64(d, d, s);         /* include sign extension */
2643     tcg_temp_free_i64(s);
2644 }
2645 
2646 void tcg_gen_vec_sar16i_i64(TCGv_i64 d, TCGv_i64 a, int64_t c)
2647 {
2648     uint64_t s_mask = dup_const(MO_16, 0x8000 >> c);
2649     uint64_t c_mask = dup_const(MO_16, 0xffff >> c);
2650     TCGv_i64 s = tcg_temp_new_i64();
2651 
2652     tcg_gen_shri_i64(d, a, c);
2653     tcg_gen_andi_i64(s, d, s_mask);  /* isolate (shifted) sign bit */
2654     tcg_gen_andi_i64(d, d, c_mask);  /* clear out bits above sign  */
2655     tcg_gen_muli_i64(s, s, (2 << c) - 2); /* replicate isolated signs */
2656     tcg_gen_or_i64(d, d, s);         /* include sign extension */
2657     tcg_temp_free_i64(s);
2658 }
2659 
2660 void tcg_gen_gvec_sari(unsigned vece, uint32_t dofs, uint32_t aofs,
2661                        int64_t shift, uint32_t oprsz, uint32_t maxsz)
2662 {
2663     static const TCGOpcode vecop_list[] = { INDEX_op_sari_vec, 0 };
2664     static const GVecGen2i g[4] = {
2665         { .fni8 = tcg_gen_vec_sar8i_i64,
2666           .fniv = tcg_gen_sari_vec,
2667           .fno = gen_helper_gvec_sar8i,
2668           .opt_opc = vecop_list,
2669           .vece = MO_8 },
2670         { .fni8 = tcg_gen_vec_sar16i_i64,
2671           .fniv = tcg_gen_sari_vec,
2672           .fno = gen_helper_gvec_sar16i,
2673           .opt_opc = vecop_list,
2674           .vece = MO_16 },
2675         { .fni4 = tcg_gen_sari_i32,
2676           .fniv = tcg_gen_sari_vec,
2677           .fno = gen_helper_gvec_sar32i,
2678           .opt_opc = vecop_list,
2679           .vece = MO_32 },
2680         { .fni8 = tcg_gen_sari_i64,
2681           .fniv = tcg_gen_sari_vec,
2682           .fno = gen_helper_gvec_sar64i,
2683           .opt_opc = vecop_list,
2684           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2685           .vece = MO_64 },
2686     };
2687 
2688     tcg_debug_assert(vece <= MO_64);
2689     tcg_debug_assert(shift >= 0 && shift < (8 << vece));
2690     if (shift == 0) {
2691         tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz);
2692     } else {
2693         tcg_gen_gvec_2i(dofs, aofs, oprsz, maxsz, shift, &g[vece]);
2694     }
2695 }
2696 
2697 /*
2698  * Specialized generation vector shifts by a non-constant scalar.
2699  */
2700 
2701 typedef struct {
2702     void (*fni4)(TCGv_i32, TCGv_i32, TCGv_i32);
2703     void (*fni8)(TCGv_i64, TCGv_i64, TCGv_i64);
2704     void (*fniv_s)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32);
2705     void (*fniv_v)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec);
2706     gen_helper_gvec_2 *fno[4];
2707     TCGOpcode s_list[2];
2708     TCGOpcode v_list[2];
2709 } GVecGen2sh;
2710 
2711 static void expand_2sh_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
2712                            uint32_t oprsz, uint32_t tysz, TCGType type,
2713                            TCGv_i32 shift,
2714                            void (*fni)(unsigned, TCGv_vec, TCGv_vec, TCGv_i32))
2715 {
2716     TCGv_vec t0 = tcg_temp_new_vec(type);
2717     uint32_t i;
2718 
2719     for (i = 0; i < oprsz; i += tysz) {
2720         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
2721         fni(vece, t0, t0, shift);
2722         tcg_gen_st_vec(t0, cpu_env, dofs + i);
2723     }
2724     tcg_temp_free_vec(t0);
2725 }
2726 
2727 static void
2728 do_gvec_shifts(unsigned vece, uint32_t dofs, uint32_t aofs, TCGv_i32 shift,
2729                uint32_t oprsz, uint32_t maxsz, const GVecGen2sh *g)
2730 {
2731     TCGType type;
2732     uint32_t some;
2733 
2734     check_size_align(oprsz, maxsz, dofs | aofs);
2735     check_overlap_2(dofs, aofs, maxsz);
2736 
2737     /* If the backend has a scalar expansion, great.  */
2738     type = choose_vector_type(g->s_list, vece, oprsz, vece == MO_64);
2739     if (type) {
2740         const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
2741         switch (type) {
2742         case TCG_TYPE_V256:
2743             some = QEMU_ALIGN_DOWN(oprsz, 32);
2744             expand_2sh_vec(vece, dofs, aofs, some, 32,
2745                            TCG_TYPE_V256, shift, g->fniv_s);
2746             if (some == oprsz) {
2747                 break;
2748             }
2749             dofs += some;
2750             aofs += some;
2751             oprsz -= some;
2752             maxsz -= some;
2753             /* fallthru */
2754         case TCG_TYPE_V128:
2755             expand_2sh_vec(vece, dofs, aofs, oprsz, 16,
2756                            TCG_TYPE_V128, shift, g->fniv_s);
2757             break;
2758         case TCG_TYPE_V64:
2759             expand_2sh_vec(vece, dofs, aofs, oprsz, 8,
2760                            TCG_TYPE_V64, shift, g->fniv_s);
2761             break;
2762         default:
2763             g_assert_not_reached();
2764         }
2765         tcg_swap_vecop_list(hold_list);
2766         goto clear_tail;
2767     }
2768 
2769     /* If the backend supports variable vector shifts, also cool.  */
2770     type = choose_vector_type(g->v_list, vece, oprsz, vece == MO_64);
2771     if (type) {
2772         const TCGOpcode *hold_list = tcg_swap_vecop_list(NULL);
2773         TCGv_vec v_shift = tcg_temp_new_vec(type);
2774 
2775         if (vece == MO_64) {
2776             TCGv_i64 sh64 = tcg_temp_new_i64();
2777             tcg_gen_extu_i32_i64(sh64, shift);
2778             tcg_gen_dup_i64_vec(MO_64, v_shift, sh64);
2779             tcg_temp_free_i64(sh64);
2780         } else {
2781             tcg_gen_dup_i32_vec(vece, v_shift, shift);
2782         }
2783 
2784         switch (type) {
2785         case TCG_TYPE_V256:
2786             some = QEMU_ALIGN_DOWN(oprsz, 32);
2787             expand_2s_vec(vece, dofs, aofs, some, 32, TCG_TYPE_V256,
2788                           v_shift, false, g->fniv_v);
2789             if (some == oprsz) {
2790                 break;
2791             }
2792             dofs += some;
2793             aofs += some;
2794             oprsz -= some;
2795             maxsz -= some;
2796             /* fallthru */
2797         case TCG_TYPE_V128:
2798             expand_2s_vec(vece, dofs, aofs, oprsz, 16, TCG_TYPE_V128,
2799                           v_shift, false, g->fniv_v);
2800             break;
2801         case TCG_TYPE_V64:
2802             expand_2s_vec(vece, dofs, aofs, oprsz, 8, TCG_TYPE_V64,
2803                           v_shift, false, g->fniv_v);
2804             break;
2805         default:
2806             g_assert_not_reached();
2807         }
2808         tcg_temp_free_vec(v_shift);
2809         tcg_swap_vecop_list(hold_list);
2810         goto clear_tail;
2811     }
2812 
2813     /* Otherwise fall back to integral... */
2814     if (vece == MO_32 && check_size_impl(oprsz, 4)) {
2815         expand_2s_i32(dofs, aofs, oprsz, shift, false, g->fni4);
2816     } else if (vece == MO_64 && check_size_impl(oprsz, 8)) {
2817         TCGv_i64 sh64 = tcg_temp_new_i64();
2818         tcg_gen_extu_i32_i64(sh64, shift);
2819         expand_2s_i64(dofs, aofs, oprsz, sh64, false, g->fni8);
2820         tcg_temp_free_i64(sh64);
2821     } else {
2822         TCGv_ptr a0 = tcg_temp_new_ptr();
2823         TCGv_ptr a1 = tcg_temp_new_ptr();
2824         TCGv_i32 desc = tcg_temp_new_i32();
2825 
2826         tcg_gen_shli_i32(desc, shift, SIMD_DATA_SHIFT);
2827         tcg_gen_ori_i32(desc, desc, simd_desc(oprsz, maxsz, 0));
2828         tcg_gen_addi_ptr(a0, cpu_env, dofs);
2829         tcg_gen_addi_ptr(a1, cpu_env, aofs);
2830 
2831         g->fno[vece](a0, a1, desc);
2832 
2833         tcg_temp_free_ptr(a0);
2834         tcg_temp_free_ptr(a1);
2835         tcg_temp_free_i32(desc);
2836         return;
2837     }
2838 
2839  clear_tail:
2840     if (oprsz < maxsz) {
2841         expand_clr(dofs + oprsz, maxsz - oprsz);
2842     }
2843 }
2844 
2845 void tcg_gen_gvec_shls(unsigned vece, uint32_t dofs, uint32_t aofs,
2846                        TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
2847 {
2848     static const GVecGen2sh g = {
2849         .fni4 = tcg_gen_shl_i32,
2850         .fni8 = tcg_gen_shl_i64,
2851         .fniv_s = tcg_gen_shls_vec,
2852         .fniv_v = tcg_gen_shlv_vec,
2853         .fno = {
2854             gen_helper_gvec_shl8i,
2855             gen_helper_gvec_shl16i,
2856             gen_helper_gvec_shl32i,
2857             gen_helper_gvec_shl64i,
2858         },
2859         .s_list = { INDEX_op_shls_vec, 0 },
2860         .v_list = { INDEX_op_shlv_vec, 0 },
2861     };
2862 
2863     tcg_debug_assert(vece <= MO_64);
2864     do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
2865 }
2866 
2867 void tcg_gen_gvec_shrs(unsigned vece, uint32_t dofs, uint32_t aofs,
2868                        TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
2869 {
2870     static const GVecGen2sh g = {
2871         .fni4 = tcg_gen_shr_i32,
2872         .fni8 = tcg_gen_shr_i64,
2873         .fniv_s = tcg_gen_shrs_vec,
2874         .fniv_v = tcg_gen_shrv_vec,
2875         .fno = {
2876             gen_helper_gvec_shr8i,
2877             gen_helper_gvec_shr16i,
2878             gen_helper_gvec_shr32i,
2879             gen_helper_gvec_shr64i,
2880         },
2881         .s_list = { INDEX_op_shrs_vec, 0 },
2882         .v_list = { INDEX_op_shrv_vec, 0 },
2883     };
2884 
2885     tcg_debug_assert(vece <= MO_64);
2886     do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
2887 }
2888 
2889 void tcg_gen_gvec_sars(unsigned vece, uint32_t dofs, uint32_t aofs,
2890                        TCGv_i32 shift, uint32_t oprsz, uint32_t maxsz)
2891 {
2892     static const GVecGen2sh g = {
2893         .fni4 = tcg_gen_sar_i32,
2894         .fni8 = tcg_gen_sar_i64,
2895         .fniv_s = tcg_gen_sars_vec,
2896         .fniv_v = tcg_gen_sarv_vec,
2897         .fno = {
2898             gen_helper_gvec_sar8i,
2899             gen_helper_gvec_sar16i,
2900             gen_helper_gvec_sar32i,
2901             gen_helper_gvec_sar64i,
2902         },
2903         .s_list = { INDEX_op_sars_vec, 0 },
2904         .v_list = { INDEX_op_sarv_vec, 0 },
2905     };
2906 
2907     tcg_debug_assert(vece <= MO_64);
2908     do_gvec_shifts(vece, dofs, aofs, shift, oprsz, maxsz, &g);
2909 }
2910 
2911 /*
2912  * Expand D = A << (B % element bits)
2913  *
2914  * Unlike scalar shifts, where it is easy for the target front end
2915  * to include the modulo as part of the expansion.  If the target
2916  * naturally includes the modulo as part of the operation, great!
2917  * If the target has some other behaviour from out-of-range shifts,
2918  * then it could not use this function anyway, and would need to
2919  * do it's own expansion with custom functions.
2920  */
2921 static void tcg_gen_shlv_mod_vec(unsigned vece, TCGv_vec d,
2922                                  TCGv_vec a, TCGv_vec b)
2923 {
2924     TCGv_vec t = tcg_temp_new_vec_matching(d);
2925 
2926     tcg_gen_dupi_vec(vece, t, (8 << vece) - 1);
2927     tcg_gen_and_vec(vece, t, t, b);
2928     tcg_gen_shlv_vec(vece, d, a, t);
2929     tcg_temp_free_vec(t);
2930 }
2931 
2932 static void tcg_gen_shl_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
2933 {
2934     TCGv_i32 t = tcg_temp_new_i32();
2935 
2936     tcg_gen_andi_i32(t, b, 31);
2937     tcg_gen_shl_i32(d, a, t);
2938     tcg_temp_free_i32(t);
2939 }
2940 
2941 static void tcg_gen_shl_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
2942 {
2943     TCGv_i64 t = tcg_temp_new_i64();
2944 
2945     tcg_gen_andi_i64(t, b, 63);
2946     tcg_gen_shl_i64(d, a, t);
2947     tcg_temp_free_i64(t);
2948 }
2949 
2950 void tcg_gen_gvec_shlv(unsigned vece, uint32_t dofs, uint32_t aofs,
2951                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
2952 {
2953     static const TCGOpcode vecop_list[] = { INDEX_op_shlv_vec, 0 };
2954     static const GVecGen3 g[4] = {
2955         { .fniv = tcg_gen_shlv_mod_vec,
2956           .fno = gen_helper_gvec_shl8v,
2957           .opt_opc = vecop_list,
2958           .vece = MO_8 },
2959         { .fniv = tcg_gen_shlv_mod_vec,
2960           .fno = gen_helper_gvec_shl16v,
2961           .opt_opc = vecop_list,
2962           .vece = MO_16 },
2963         { .fni4 = tcg_gen_shl_mod_i32,
2964           .fniv = tcg_gen_shlv_mod_vec,
2965           .fno = gen_helper_gvec_shl32v,
2966           .opt_opc = vecop_list,
2967           .vece = MO_32 },
2968         { .fni8 = tcg_gen_shl_mod_i64,
2969           .fniv = tcg_gen_shlv_mod_vec,
2970           .fno = gen_helper_gvec_shl64v,
2971           .opt_opc = vecop_list,
2972           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
2973           .vece = MO_64 },
2974     };
2975 
2976     tcg_debug_assert(vece <= MO_64);
2977     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
2978 }
2979 
2980 /*
2981  * Similarly for logical right shifts.
2982  */
2983 
2984 static void tcg_gen_shrv_mod_vec(unsigned vece, TCGv_vec d,
2985                                  TCGv_vec a, TCGv_vec b)
2986 {
2987     TCGv_vec t = tcg_temp_new_vec_matching(d);
2988 
2989     tcg_gen_dupi_vec(vece, t, (8 << vece) - 1);
2990     tcg_gen_and_vec(vece, t, t, b);
2991     tcg_gen_shrv_vec(vece, d, a, t);
2992     tcg_temp_free_vec(t);
2993 }
2994 
2995 static void tcg_gen_shr_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
2996 {
2997     TCGv_i32 t = tcg_temp_new_i32();
2998 
2999     tcg_gen_andi_i32(t, b, 31);
3000     tcg_gen_shr_i32(d, a, t);
3001     tcg_temp_free_i32(t);
3002 }
3003 
3004 static void tcg_gen_shr_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3005 {
3006     TCGv_i64 t = tcg_temp_new_i64();
3007 
3008     tcg_gen_andi_i64(t, b, 63);
3009     tcg_gen_shr_i64(d, a, t);
3010     tcg_temp_free_i64(t);
3011 }
3012 
3013 void tcg_gen_gvec_shrv(unsigned vece, uint32_t dofs, uint32_t aofs,
3014                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
3015 {
3016     static const TCGOpcode vecop_list[] = { INDEX_op_shrv_vec, 0 };
3017     static const GVecGen3 g[4] = {
3018         { .fniv = tcg_gen_shrv_mod_vec,
3019           .fno = gen_helper_gvec_shr8v,
3020           .opt_opc = vecop_list,
3021           .vece = MO_8 },
3022         { .fniv = tcg_gen_shrv_mod_vec,
3023           .fno = gen_helper_gvec_shr16v,
3024           .opt_opc = vecop_list,
3025           .vece = MO_16 },
3026         { .fni4 = tcg_gen_shr_mod_i32,
3027           .fniv = tcg_gen_shrv_mod_vec,
3028           .fno = gen_helper_gvec_shr32v,
3029           .opt_opc = vecop_list,
3030           .vece = MO_32 },
3031         { .fni8 = tcg_gen_shr_mod_i64,
3032           .fniv = tcg_gen_shrv_mod_vec,
3033           .fno = gen_helper_gvec_shr64v,
3034           .opt_opc = vecop_list,
3035           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3036           .vece = MO_64 },
3037     };
3038 
3039     tcg_debug_assert(vece <= MO_64);
3040     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
3041 }
3042 
3043 /*
3044  * Similarly for arithmetic right shifts.
3045  */
3046 
3047 static void tcg_gen_sarv_mod_vec(unsigned vece, TCGv_vec d,
3048                                  TCGv_vec a, TCGv_vec b)
3049 {
3050     TCGv_vec t = tcg_temp_new_vec_matching(d);
3051 
3052     tcg_gen_dupi_vec(vece, t, (8 << vece) - 1);
3053     tcg_gen_and_vec(vece, t, t, b);
3054     tcg_gen_sarv_vec(vece, d, a, t);
3055     tcg_temp_free_vec(t);
3056 }
3057 
3058 static void tcg_gen_sar_mod_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
3059 {
3060     TCGv_i32 t = tcg_temp_new_i32();
3061 
3062     tcg_gen_andi_i32(t, b, 31);
3063     tcg_gen_sar_i32(d, a, t);
3064     tcg_temp_free_i32(t);
3065 }
3066 
3067 static void tcg_gen_sar_mod_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
3068 {
3069     TCGv_i64 t = tcg_temp_new_i64();
3070 
3071     tcg_gen_andi_i64(t, b, 63);
3072     tcg_gen_sar_i64(d, a, t);
3073     tcg_temp_free_i64(t);
3074 }
3075 
3076 void tcg_gen_gvec_sarv(unsigned vece, uint32_t dofs, uint32_t aofs,
3077                        uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
3078 {
3079     static const TCGOpcode vecop_list[] = { INDEX_op_sarv_vec, 0 };
3080     static const GVecGen3 g[4] = {
3081         { .fniv = tcg_gen_sarv_mod_vec,
3082           .fno = gen_helper_gvec_sar8v,
3083           .opt_opc = vecop_list,
3084           .vece = MO_8 },
3085         { .fniv = tcg_gen_sarv_mod_vec,
3086           .fno = gen_helper_gvec_sar16v,
3087           .opt_opc = vecop_list,
3088           .vece = MO_16 },
3089         { .fni4 = tcg_gen_sar_mod_i32,
3090           .fniv = tcg_gen_sarv_mod_vec,
3091           .fno = gen_helper_gvec_sar32v,
3092           .opt_opc = vecop_list,
3093           .vece = MO_32 },
3094         { .fni8 = tcg_gen_sar_mod_i64,
3095           .fniv = tcg_gen_sarv_mod_vec,
3096           .fno = gen_helper_gvec_sar64v,
3097           .opt_opc = vecop_list,
3098           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3099           .vece = MO_64 },
3100     };
3101 
3102     tcg_debug_assert(vece <= MO_64);
3103     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &g[vece]);
3104 }
3105 
3106 /* Expand OPSZ bytes worth of three-operand operations using i32 elements.  */
3107 static void expand_cmp_i32(uint32_t dofs, uint32_t aofs, uint32_t bofs,
3108                            uint32_t oprsz, TCGCond cond)
3109 {
3110     TCGv_i32 t0 = tcg_temp_new_i32();
3111     TCGv_i32 t1 = tcg_temp_new_i32();
3112     uint32_t i;
3113 
3114     for (i = 0; i < oprsz; i += 4) {
3115         tcg_gen_ld_i32(t0, cpu_env, aofs + i);
3116         tcg_gen_ld_i32(t1, cpu_env, bofs + i);
3117         tcg_gen_setcond_i32(cond, t0, t0, t1);
3118         tcg_gen_neg_i32(t0, t0);
3119         tcg_gen_st_i32(t0, cpu_env, dofs + i);
3120     }
3121     tcg_temp_free_i32(t1);
3122     tcg_temp_free_i32(t0);
3123 }
3124 
3125 static void expand_cmp_i64(uint32_t dofs, uint32_t aofs, uint32_t bofs,
3126                            uint32_t oprsz, TCGCond cond)
3127 {
3128     TCGv_i64 t0 = tcg_temp_new_i64();
3129     TCGv_i64 t1 = tcg_temp_new_i64();
3130     uint32_t i;
3131 
3132     for (i = 0; i < oprsz; i += 8) {
3133         tcg_gen_ld_i64(t0, cpu_env, aofs + i);
3134         tcg_gen_ld_i64(t1, cpu_env, bofs + i);
3135         tcg_gen_setcond_i64(cond, t0, t0, t1);
3136         tcg_gen_neg_i64(t0, t0);
3137         tcg_gen_st_i64(t0, cpu_env, dofs + i);
3138     }
3139     tcg_temp_free_i64(t1);
3140     tcg_temp_free_i64(t0);
3141 }
3142 
3143 static void expand_cmp_vec(unsigned vece, uint32_t dofs, uint32_t aofs,
3144                            uint32_t bofs, uint32_t oprsz, uint32_t tysz,
3145                            TCGType type, TCGCond cond)
3146 {
3147     TCGv_vec t0 = tcg_temp_new_vec(type);
3148     TCGv_vec t1 = tcg_temp_new_vec(type);
3149     uint32_t i;
3150 
3151     for (i = 0; i < oprsz; i += tysz) {
3152         tcg_gen_ld_vec(t0, cpu_env, aofs + i);
3153         tcg_gen_ld_vec(t1, cpu_env, bofs + i);
3154         tcg_gen_cmp_vec(cond, vece, t0, t0, t1);
3155         tcg_gen_st_vec(t0, cpu_env, dofs + i);
3156     }
3157     tcg_temp_free_vec(t1);
3158     tcg_temp_free_vec(t0);
3159 }
3160 
3161 void tcg_gen_gvec_cmp(TCGCond cond, unsigned vece, uint32_t dofs,
3162                       uint32_t aofs, uint32_t bofs,
3163                       uint32_t oprsz, uint32_t maxsz)
3164 {
3165     static const TCGOpcode cmp_list[] = { INDEX_op_cmp_vec, 0 };
3166     static gen_helper_gvec_3 * const eq_fn[4] = {
3167         gen_helper_gvec_eq8, gen_helper_gvec_eq16,
3168         gen_helper_gvec_eq32, gen_helper_gvec_eq64
3169     };
3170     static gen_helper_gvec_3 * const ne_fn[4] = {
3171         gen_helper_gvec_ne8, gen_helper_gvec_ne16,
3172         gen_helper_gvec_ne32, gen_helper_gvec_ne64
3173     };
3174     static gen_helper_gvec_3 * const lt_fn[4] = {
3175         gen_helper_gvec_lt8, gen_helper_gvec_lt16,
3176         gen_helper_gvec_lt32, gen_helper_gvec_lt64
3177     };
3178     static gen_helper_gvec_3 * const le_fn[4] = {
3179         gen_helper_gvec_le8, gen_helper_gvec_le16,
3180         gen_helper_gvec_le32, gen_helper_gvec_le64
3181     };
3182     static gen_helper_gvec_3 * const ltu_fn[4] = {
3183         gen_helper_gvec_ltu8, gen_helper_gvec_ltu16,
3184         gen_helper_gvec_ltu32, gen_helper_gvec_ltu64
3185     };
3186     static gen_helper_gvec_3 * const leu_fn[4] = {
3187         gen_helper_gvec_leu8, gen_helper_gvec_leu16,
3188         gen_helper_gvec_leu32, gen_helper_gvec_leu64
3189     };
3190     static gen_helper_gvec_3 * const * const fns[16] = {
3191         [TCG_COND_EQ] = eq_fn,
3192         [TCG_COND_NE] = ne_fn,
3193         [TCG_COND_LT] = lt_fn,
3194         [TCG_COND_LE] = le_fn,
3195         [TCG_COND_LTU] = ltu_fn,
3196         [TCG_COND_LEU] = leu_fn,
3197     };
3198 
3199     const TCGOpcode *hold_list;
3200     TCGType type;
3201     uint32_t some;
3202 
3203     check_size_align(oprsz, maxsz, dofs | aofs | bofs);
3204     check_overlap_3(dofs, aofs, bofs, maxsz);
3205 
3206     if (cond == TCG_COND_NEVER || cond == TCG_COND_ALWAYS) {
3207         do_dup(MO_8, dofs, oprsz, maxsz,
3208                NULL, NULL, -(cond == TCG_COND_ALWAYS));
3209         return;
3210     }
3211 
3212     /*
3213      * Implement inline with a vector type, if possible.
3214      * Prefer integer when 64-bit host and 64-bit comparison.
3215      */
3216     hold_list = tcg_swap_vecop_list(cmp_list);
3217     type = choose_vector_type(cmp_list, vece, oprsz,
3218                               TCG_TARGET_REG_BITS == 64 && vece == MO_64);
3219     switch (type) {
3220     case TCG_TYPE_V256:
3221         /* Recall that ARM SVE allows vector sizes that are not a
3222          * power of 2, but always a multiple of 16.  The intent is
3223          * that e.g. size == 80 would be expanded with 2x32 + 1x16.
3224          */
3225         some = QEMU_ALIGN_DOWN(oprsz, 32);
3226         expand_cmp_vec(vece, dofs, aofs, bofs, some, 32, TCG_TYPE_V256, cond);
3227         if (some == oprsz) {
3228             break;
3229         }
3230         dofs += some;
3231         aofs += some;
3232         bofs += some;
3233         oprsz -= some;
3234         maxsz -= some;
3235         /* fallthru */
3236     case TCG_TYPE_V128:
3237         expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 16, TCG_TYPE_V128, cond);
3238         break;
3239     case TCG_TYPE_V64:
3240         expand_cmp_vec(vece, dofs, aofs, bofs, oprsz, 8, TCG_TYPE_V64, cond);
3241         break;
3242 
3243     case 0:
3244         if (vece == MO_64 && check_size_impl(oprsz, 8)) {
3245             expand_cmp_i64(dofs, aofs, bofs, oprsz, cond);
3246         } else if (vece == MO_32 && check_size_impl(oprsz, 4)) {
3247             expand_cmp_i32(dofs, aofs, bofs, oprsz, cond);
3248         } else {
3249             gen_helper_gvec_3 * const *fn = fns[cond];
3250 
3251             if (fn == NULL) {
3252                 uint32_t tmp;
3253                 tmp = aofs, aofs = bofs, bofs = tmp;
3254                 cond = tcg_swap_cond(cond);
3255                 fn = fns[cond];
3256                 assert(fn != NULL);
3257             }
3258             tcg_gen_gvec_3_ool(dofs, aofs, bofs, oprsz, maxsz, 0, fn[vece]);
3259             oprsz = maxsz;
3260         }
3261         break;
3262 
3263     default:
3264         g_assert_not_reached();
3265     }
3266     tcg_swap_vecop_list(hold_list);
3267 
3268     if (oprsz < maxsz) {
3269         expand_clr(dofs + oprsz, maxsz - oprsz);
3270     }
3271 }
3272 
3273 static void tcg_gen_bitsel_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c)
3274 {
3275     TCGv_i64 t = tcg_temp_new_i64();
3276 
3277     tcg_gen_and_i64(t, b, a);
3278     tcg_gen_andc_i64(d, c, a);
3279     tcg_gen_or_i64(d, d, t);
3280     tcg_temp_free_i64(t);
3281 }
3282 
3283 void tcg_gen_gvec_bitsel(unsigned vece, uint32_t dofs, uint32_t aofs,
3284                          uint32_t bofs, uint32_t cofs,
3285                          uint32_t oprsz, uint32_t maxsz)
3286 {
3287     static const GVecGen4 g = {
3288         .fni8 = tcg_gen_bitsel_i64,
3289         .fniv = tcg_gen_bitsel_vec,
3290         .fno = gen_helper_gvec_bitsel,
3291     };
3292 
3293     tcg_gen_gvec_4(dofs, aofs, bofs, cofs, oprsz, maxsz, &g);
3294 }
3295