target/loongarch: Implement vmax/vmin
[qemu/armbru.git] / target / loongarch / insn_trans / trans_lsx.c.inc
blob15bb7888d3dfb83500613d5d2170e6378537f73e
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * LSX translate functions
4  * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
5  */
7 #ifndef CONFIG_USER_ONLY
8 #define CHECK_SXE do { \
9     if ((ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0) { \
10         generate_exception(ctx, EXCCODE_SXD); \
11         return true; \
12     } \
13 } while (0)
14 #else
15 #define CHECK_SXE
16 #endif
18 static bool gen_vvv(DisasContext *ctx, arg_vvv *a,
19                     void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32))
21     TCGv_i32 vd = tcg_constant_i32(a->vd);
22     TCGv_i32 vj = tcg_constant_i32(a->vj);
23     TCGv_i32 vk = tcg_constant_i32(a->vk);
25     CHECK_SXE;
27     func(cpu_env, vd, vj, vk);
28     return true;
31 static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
32                      void (*func)(unsigned, uint32_t, uint32_t,
33                                   uint32_t, uint32_t, uint32_t))
35     uint32_t vd_ofs, vj_ofs, vk_ofs;
37     CHECK_SXE;
39     vd_ofs = vec_full_offset(a->vd);
40     vj_ofs = vec_full_offset(a->vj);
41     vk_ofs = vec_full_offset(a->vk);
43     func(mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
44     return true;
47 static bool gvec_vv(DisasContext *ctx, arg_vv *a, MemOp mop,
48                     void (*func)(unsigned, uint32_t, uint32_t,
49                                  uint32_t, uint32_t))
51     uint32_t vd_ofs, vj_ofs;
53     CHECK_SXE;
55     vd_ofs = vec_full_offset(a->vd);
56     vj_ofs = vec_full_offset(a->vj);
58     func(mop, vd_ofs, vj_ofs, 16, ctx->vl/8);
59     return true;
62 static bool gvec_vv_i(DisasContext *ctx, arg_vv_i *a, MemOp mop,
63                       void (*func)(unsigned, uint32_t, uint32_t,
64                                    int64_t, uint32_t, uint32_t))
66     uint32_t vd_ofs, vj_ofs;
68     CHECK_SXE;
70     vd_ofs = vec_full_offset(a->vd);
71     vj_ofs = vec_full_offset(a->vj);
73     func(mop, vd_ofs, vj_ofs, a->imm , 16, ctx->vl/8);
74     return true;
77 static bool gvec_subi(DisasContext *ctx, arg_vv_i *a, MemOp mop)
79     uint32_t vd_ofs, vj_ofs;
81     CHECK_SXE;
83     vd_ofs = vec_full_offset(a->vd);
84     vj_ofs = vec_full_offset(a->vj);
86     tcg_gen_gvec_addi(mop, vd_ofs, vj_ofs, -a->imm, 16, ctx->vl/8);
87     return true;
90 TRANS(vadd_b, gvec_vvv, MO_8, tcg_gen_gvec_add)
91 TRANS(vadd_h, gvec_vvv, MO_16, tcg_gen_gvec_add)
92 TRANS(vadd_w, gvec_vvv, MO_32, tcg_gen_gvec_add)
93 TRANS(vadd_d, gvec_vvv, MO_64, tcg_gen_gvec_add)
95 #define VADDSUB_Q(NAME)                                        \
96 static bool trans_v## NAME ##_q(DisasContext *ctx, arg_vvv *a) \
97 {                                                              \
98     TCGv_i64 rh, rl, ah, al, bh, bl;                           \
99                                                                \
100     CHECK_SXE;                                                 \
101                                                                \
102     rh = tcg_temp_new_i64();                                   \
103     rl = tcg_temp_new_i64();                                   \
104     ah = tcg_temp_new_i64();                                   \
105     al = tcg_temp_new_i64();                                   \
106     bh = tcg_temp_new_i64();                                   \
107     bl = tcg_temp_new_i64();                                   \
108                                                                \
109     get_vreg64(ah, a->vj, 1);                                  \
110     get_vreg64(al, a->vj, 0);                                  \
111     get_vreg64(bh, a->vk, 1);                                  \
112     get_vreg64(bl, a->vk, 0);                                  \
113                                                                \
114     tcg_gen_## NAME ##2_i64(rl, rh, al, ah, bl, bh);           \
115                                                                \
116     set_vreg64(rh, a->vd, 1);                                  \
117     set_vreg64(rl, a->vd, 0);                                  \
118                                                                \
119     return true;                                               \
122 VADDSUB_Q(add)
123 VADDSUB_Q(sub)
125 TRANS(vsub_b, gvec_vvv, MO_8, tcg_gen_gvec_sub)
126 TRANS(vsub_h, gvec_vvv, MO_16, tcg_gen_gvec_sub)
127 TRANS(vsub_w, gvec_vvv, MO_32, tcg_gen_gvec_sub)
128 TRANS(vsub_d, gvec_vvv, MO_64, tcg_gen_gvec_sub)
130 TRANS(vaddi_bu, gvec_vv_i, MO_8, tcg_gen_gvec_addi)
131 TRANS(vaddi_hu, gvec_vv_i, MO_16, tcg_gen_gvec_addi)
132 TRANS(vaddi_wu, gvec_vv_i, MO_32, tcg_gen_gvec_addi)
133 TRANS(vaddi_du, gvec_vv_i, MO_64, tcg_gen_gvec_addi)
134 TRANS(vsubi_bu, gvec_subi, MO_8)
135 TRANS(vsubi_hu, gvec_subi, MO_16)
136 TRANS(vsubi_wu, gvec_subi, MO_32)
137 TRANS(vsubi_du, gvec_subi, MO_64)
139 TRANS(vneg_b, gvec_vv, MO_8, tcg_gen_gvec_neg)
140 TRANS(vneg_h, gvec_vv, MO_16, tcg_gen_gvec_neg)
141 TRANS(vneg_w, gvec_vv, MO_32, tcg_gen_gvec_neg)
142 TRANS(vneg_d, gvec_vv, MO_64, tcg_gen_gvec_neg)
144 TRANS(vsadd_b, gvec_vvv, MO_8, tcg_gen_gvec_ssadd)
145 TRANS(vsadd_h, gvec_vvv, MO_16, tcg_gen_gvec_ssadd)
146 TRANS(vsadd_w, gvec_vvv, MO_32, tcg_gen_gvec_ssadd)
147 TRANS(vsadd_d, gvec_vvv, MO_64, tcg_gen_gvec_ssadd)
148 TRANS(vsadd_bu, gvec_vvv, MO_8, tcg_gen_gvec_usadd)
149 TRANS(vsadd_hu, gvec_vvv, MO_16, tcg_gen_gvec_usadd)
150 TRANS(vsadd_wu, gvec_vvv, MO_32, tcg_gen_gvec_usadd)
151 TRANS(vsadd_du, gvec_vvv, MO_64, tcg_gen_gvec_usadd)
152 TRANS(vssub_b, gvec_vvv, MO_8, tcg_gen_gvec_sssub)
153 TRANS(vssub_h, gvec_vvv, MO_16, tcg_gen_gvec_sssub)
154 TRANS(vssub_w, gvec_vvv, MO_32, tcg_gen_gvec_sssub)
155 TRANS(vssub_d, gvec_vvv, MO_64, tcg_gen_gvec_sssub)
156 TRANS(vssub_bu, gvec_vvv, MO_8, tcg_gen_gvec_ussub)
157 TRANS(vssub_hu, gvec_vvv, MO_16, tcg_gen_gvec_ussub)
158 TRANS(vssub_wu, gvec_vvv, MO_32, tcg_gen_gvec_ussub)
159 TRANS(vssub_du, gvec_vvv, MO_64, tcg_gen_gvec_ussub)
161 TRANS(vhaddw_h_b, gen_vvv, gen_helper_vhaddw_h_b)
162 TRANS(vhaddw_w_h, gen_vvv, gen_helper_vhaddw_w_h)
163 TRANS(vhaddw_d_w, gen_vvv, gen_helper_vhaddw_d_w)
164 TRANS(vhaddw_q_d, gen_vvv, gen_helper_vhaddw_q_d)
165 TRANS(vhaddw_hu_bu, gen_vvv, gen_helper_vhaddw_hu_bu)
166 TRANS(vhaddw_wu_hu, gen_vvv, gen_helper_vhaddw_wu_hu)
167 TRANS(vhaddw_du_wu, gen_vvv, gen_helper_vhaddw_du_wu)
168 TRANS(vhaddw_qu_du, gen_vvv, gen_helper_vhaddw_qu_du)
169 TRANS(vhsubw_h_b, gen_vvv, gen_helper_vhsubw_h_b)
170 TRANS(vhsubw_w_h, gen_vvv, gen_helper_vhsubw_w_h)
171 TRANS(vhsubw_d_w, gen_vvv, gen_helper_vhsubw_d_w)
172 TRANS(vhsubw_q_d, gen_vvv, gen_helper_vhsubw_q_d)
173 TRANS(vhsubw_hu_bu, gen_vvv, gen_helper_vhsubw_hu_bu)
174 TRANS(vhsubw_wu_hu, gen_vvv, gen_helper_vhsubw_wu_hu)
175 TRANS(vhsubw_du_wu, gen_vvv, gen_helper_vhsubw_du_wu)
176 TRANS(vhsubw_qu_du, gen_vvv, gen_helper_vhsubw_qu_du)
178 static void gen_vaddwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
180     TCGv_vec t1, t2;
182     int halfbits = 4 << vece;
184     t1 = tcg_temp_new_vec_matching(a);
185     t2 = tcg_temp_new_vec_matching(b);
187     /* Sign-extend the even elements from a */
188     tcg_gen_shli_vec(vece, t1, a, halfbits);
189     tcg_gen_sari_vec(vece, t1, t1, halfbits);
191     /* Sign-extend the even elements from b */
192     tcg_gen_shli_vec(vece, t2, b, halfbits);
193     tcg_gen_sari_vec(vece, t2, t2, halfbits);
195     tcg_gen_add_vec(vece, t, t1, t2);
198 static void gen_vaddwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
200     TCGv_i32 t1, t2;
202     t1 = tcg_temp_new_i32();
203     t2 = tcg_temp_new_i32();
204     tcg_gen_ext16s_i32(t1, a);
205     tcg_gen_ext16s_i32(t2, b);
206     tcg_gen_add_i32(t, t1, t2);
209 static void gen_vaddwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
211     TCGv_i64 t1, t2;
213     t1 = tcg_temp_new_i64();
214     t2 = tcg_temp_new_i64();
215     tcg_gen_ext32s_i64(t1, a);
216     tcg_gen_ext32s_i64(t2, b);
217     tcg_gen_add_i64(t, t1, t2);
220 static void do_vaddwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
221                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
223     static const TCGOpcode vecop_list[] = {
224         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
225         };
226     static const GVecGen3 op[4] = {
227         {
228             .fniv = gen_vaddwev_s,
229             .fno = gen_helper_vaddwev_h_b,
230             .opt_opc = vecop_list,
231             .vece = MO_16
232         },
233         {
234             .fni4 = gen_vaddwev_w_h,
235             .fniv = gen_vaddwev_s,
236             .fno = gen_helper_vaddwev_w_h,
237             .opt_opc = vecop_list,
238             .vece = MO_32
239         },
240         {
241             .fni8 = gen_vaddwev_d_w,
242             .fniv = gen_vaddwev_s,
243             .fno = gen_helper_vaddwev_d_w,
244             .opt_opc = vecop_list,
245             .vece = MO_64
246         },
247         {
248             .fno = gen_helper_vaddwev_q_d,
249             .vece = MO_128
250         },
251     };
253     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
256 TRANS(vaddwev_h_b, gvec_vvv, MO_8, do_vaddwev_s)
257 TRANS(vaddwev_w_h, gvec_vvv, MO_16, do_vaddwev_s)
258 TRANS(vaddwev_d_w, gvec_vvv, MO_32, do_vaddwev_s)
259 TRANS(vaddwev_q_d, gvec_vvv, MO_64, do_vaddwev_s)
261 static void gen_vaddwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
263     TCGv_i32 t1, t2;
265     t1 = tcg_temp_new_i32();
266     t2 = tcg_temp_new_i32();
267     tcg_gen_sari_i32(t1, a, 16);
268     tcg_gen_sari_i32(t2, b, 16);
269     tcg_gen_add_i32(t, t1, t2);
272 static void gen_vaddwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
274     TCGv_i64 t1, t2;
276     t1 = tcg_temp_new_i64();
277     t2 = tcg_temp_new_i64();
278     tcg_gen_sari_i64(t1, a, 32);
279     tcg_gen_sari_i64(t2, b, 32);
280     tcg_gen_add_i64(t, t1, t2);
283 static void gen_vaddwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
285     TCGv_vec t1, t2;
287     int halfbits = 4 << vece;
289     t1 = tcg_temp_new_vec_matching(a);
290     t2 = tcg_temp_new_vec_matching(b);
292     /* Sign-extend the odd elements for vector */
293     tcg_gen_sari_vec(vece, t1, a, halfbits);
294     tcg_gen_sari_vec(vece, t2, b, halfbits);
296     tcg_gen_add_vec(vece, t, t1, t2);
299 static void do_vaddwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
300                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
302     static const TCGOpcode vecop_list[] = {
303         INDEX_op_sari_vec, INDEX_op_add_vec, 0
304         };
305     static const GVecGen3 op[4] = {
306         {
307             .fniv = gen_vaddwod_s,
308             .fno = gen_helper_vaddwod_h_b,
309             .opt_opc = vecop_list,
310             .vece = MO_16
311         },
312         {
313             .fni4 = gen_vaddwod_w_h,
314             .fniv = gen_vaddwod_s,
315             .fno = gen_helper_vaddwod_w_h,
316             .opt_opc = vecop_list,
317             .vece = MO_32
318         },
319         {
320             .fni8 = gen_vaddwod_d_w,
321             .fniv = gen_vaddwod_s,
322             .fno = gen_helper_vaddwod_d_w,
323             .opt_opc = vecop_list,
324             .vece = MO_64
325         },
326         {
327             .fno = gen_helper_vaddwod_q_d,
328             .vece = MO_128
329         },
330     };
332     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
335 TRANS(vaddwod_h_b, gvec_vvv, MO_8, do_vaddwod_s)
336 TRANS(vaddwod_w_h, gvec_vvv, MO_16, do_vaddwod_s)
337 TRANS(vaddwod_d_w, gvec_vvv, MO_32, do_vaddwod_s)
338 TRANS(vaddwod_q_d, gvec_vvv, MO_64, do_vaddwod_s)
340 static void gen_vsubwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
342     TCGv_vec t1, t2;
344     int halfbits = 4 << vece;
346     t1 = tcg_temp_new_vec_matching(a);
347     t2 = tcg_temp_new_vec_matching(b);
349     /* Sign-extend the even elements from a */
350     tcg_gen_shli_vec(vece, t1, a, halfbits);
351     tcg_gen_sari_vec(vece, t1, t1, halfbits);
353     /* Sign-extend the even elements from b */
354     tcg_gen_shli_vec(vece, t2, b, halfbits);
355     tcg_gen_sari_vec(vece, t2, t2, halfbits);
357     tcg_gen_sub_vec(vece, t, t1, t2);
360 static void gen_vsubwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
362     TCGv_i32 t1, t2;
364     t1 = tcg_temp_new_i32();
365     t2 = tcg_temp_new_i32();
366     tcg_gen_ext16s_i32(t1, a);
367     tcg_gen_ext16s_i32(t2, b);
368     tcg_gen_sub_i32(t, t1, t2);
371 static void gen_vsubwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
373     TCGv_i64 t1, t2;
375     t1 = tcg_temp_new_i64();
376     t2 = tcg_temp_new_i64();
377     tcg_gen_ext32s_i64(t1, a);
378     tcg_gen_ext32s_i64(t2, b);
379     tcg_gen_sub_i64(t, t1, t2);
382 static void do_vsubwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
383                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
385     static const TCGOpcode vecop_list[] = {
386         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_sub_vec, 0
387         };
388     static const GVecGen3 op[4] = {
389         {
390             .fniv = gen_vsubwev_s,
391             .fno = gen_helper_vsubwev_h_b,
392             .opt_opc = vecop_list,
393             .vece = MO_16
394         },
395         {
396             .fni4 = gen_vsubwev_w_h,
397             .fniv = gen_vsubwev_s,
398             .fno = gen_helper_vsubwev_w_h,
399             .opt_opc = vecop_list,
400             .vece = MO_32
401         },
402         {
403             .fni8 = gen_vsubwev_d_w,
404             .fniv = gen_vsubwev_s,
405             .fno = gen_helper_vsubwev_d_w,
406             .opt_opc = vecop_list,
407             .vece = MO_64
408         },
409         {
410             .fno = gen_helper_vsubwev_q_d,
411             .vece = MO_128
412         },
413     };
415     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
418 TRANS(vsubwev_h_b, gvec_vvv, MO_8, do_vsubwev_s)
419 TRANS(vsubwev_w_h, gvec_vvv, MO_16, do_vsubwev_s)
420 TRANS(vsubwev_d_w, gvec_vvv, MO_32, do_vsubwev_s)
421 TRANS(vsubwev_q_d, gvec_vvv, MO_64, do_vsubwev_s)
423 static void gen_vsubwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
425     TCGv_vec t1, t2;
427     int halfbits = 4 << vece;
429     t1 = tcg_temp_new_vec_matching(a);
430     t2 = tcg_temp_new_vec_matching(b);
432     /* Sign-extend the odd elements for vector */
433     tcg_gen_sari_vec(vece, t1, a, halfbits);
434     tcg_gen_sari_vec(vece, t2, b, halfbits);
436     tcg_gen_sub_vec(vece, t, t1, t2);
439 static void gen_vsubwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
441     TCGv_i32 t1, t2;
443     t1 = tcg_temp_new_i32();
444     t2 = tcg_temp_new_i32();
445     tcg_gen_sari_i32(t1, a, 16);
446     tcg_gen_sari_i32(t2, b, 16);
447     tcg_gen_sub_i32(t, t1, t2);
450 static void gen_vsubwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
452     TCGv_i64 t1, t2;
454     t1 = tcg_temp_new_i64();
455     t2 = tcg_temp_new_i64();
456     tcg_gen_sari_i64(t1, a, 32);
457     tcg_gen_sari_i64(t2, b, 32);
458     tcg_gen_sub_i64(t, t1, t2);
461 static void do_vsubwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
462                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
464     static const TCGOpcode vecop_list[] = {
465         INDEX_op_sari_vec, INDEX_op_sub_vec, 0
466         };
467     static const GVecGen3 op[4] = {
468         {
469             .fniv = gen_vsubwod_s,
470             .fno = gen_helper_vsubwod_h_b,
471             .opt_opc = vecop_list,
472             .vece = MO_16
473         },
474         {
475             .fni4 = gen_vsubwod_w_h,
476             .fniv = gen_vsubwod_s,
477             .fno = gen_helper_vsubwod_w_h,
478             .opt_opc = vecop_list,
479             .vece = MO_32
480         },
481         {
482             .fni8 = gen_vsubwod_d_w,
483             .fniv = gen_vsubwod_s,
484             .fno = gen_helper_vsubwod_d_w,
485             .opt_opc = vecop_list,
486             .vece = MO_64
487         },
488         {
489             .fno = gen_helper_vsubwod_q_d,
490             .vece = MO_128
491         },
492     };
494     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
497 TRANS(vsubwod_h_b, gvec_vvv, MO_8, do_vsubwod_s)
498 TRANS(vsubwod_w_h, gvec_vvv, MO_16, do_vsubwod_s)
499 TRANS(vsubwod_d_w, gvec_vvv, MO_32, do_vsubwod_s)
500 TRANS(vsubwod_q_d, gvec_vvv, MO_64, do_vsubwod_s)
502 static void gen_vaddwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
504     TCGv_vec t1, t2, t3;
506     t1 = tcg_temp_new_vec_matching(a);
507     t2 = tcg_temp_new_vec_matching(b);
508     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
509     tcg_gen_and_vec(vece, t1, a, t3);
510     tcg_gen_and_vec(vece, t2, b, t3);
511     tcg_gen_add_vec(vece, t, t1, t2);
514 static void gen_vaddwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
516     TCGv_i32 t1, t2;
518     t1 = tcg_temp_new_i32();
519     t2 = tcg_temp_new_i32();
520     tcg_gen_ext16u_i32(t1, a);
521     tcg_gen_ext16u_i32(t2, b);
522     tcg_gen_add_i32(t, t1, t2);
525 static void gen_vaddwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
527     TCGv_i64 t1, t2;
529     t1 = tcg_temp_new_i64();
530     t2 = tcg_temp_new_i64();
531     tcg_gen_ext32u_i64(t1, a);
532     tcg_gen_ext32u_i64(t2, b);
533     tcg_gen_add_i64(t, t1, t2);
536 static void do_vaddwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
537                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
539     static const TCGOpcode vecop_list[] = {
540         INDEX_op_add_vec, 0
541         };
542     static const GVecGen3 op[4] = {
543         {
544             .fniv = gen_vaddwev_u,
545             .fno = gen_helper_vaddwev_h_bu,
546             .opt_opc = vecop_list,
547             .vece = MO_16
548         },
549         {
550             .fni4 = gen_vaddwev_w_hu,
551             .fniv = gen_vaddwev_u,
552             .fno = gen_helper_vaddwev_w_hu,
553             .opt_opc = vecop_list,
554             .vece = MO_32
555         },
556         {
557             .fni8 = gen_vaddwev_d_wu,
558             .fniv = gen_vaddwev_u,
559             .fno = gen_helper_vaddwev_d_wu,
560             .opt_opc = vecop_list,
561             .vece = MO_64
562         },
563         {
564             .fno = gen_helper_vaddwev_q_du,
565             .vece = MO_128
566         },
567     };
569     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
572 TRANS(vaddwev_h_bu, gvec_vvv, MO_8, do_vaddwev_u)
573 TRANS(vaddwev_w_hu, gvec_vvv, MO_16, do_vaddwev_u)
574 TRANS(vaddwev_d_wu, gvec_vvv, MO_32, do_vaddwev_u)
575 TRANS(vaddwev_q_du, gvec_vvv, MO_64, do_vaddwev_u)
577 static void gen_vaddwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
579     TCGv_vec t1, t2;
581     int halfbits = 4 << vece;
583     t1 = tcg_temp_new_vec_matching(a);
584     t2 = tcg_temp_new_vec_matching(b);
586     /* Zero-extend the odd elements for vector */
587     tcg_gen_shri_vec(vece, t1, a, halfbits);
588     tcg_gen_shri_vec(vece, t2, b, halfbits);
590     tcg_gen_add_vec(vece, t, t1, t2);
593 static void gen_vaddwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
595     TCGv_i32 t1, t2;
597     t1 = tcg_temp_new_i32();
598     t2 = tcg_temp_new_i32();
599     tcg_gen_shri_i32(t1, a, 16);
600     tcg_gen_shri_i32(t2, b, 16);
601     tcg_gen_add_i32(t, t1, t2);
604 static void gen_vaddwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
606     TCGv_i64 t1, t2;
608     t1 = tcg_temp_new_i64();
609     t2 = tcg_temp_new_i64();
610     tcg_gen_shri_i64(t1, a, 32);
611     tcg_gen_shri_i64(t2, b, 32);
612     tcg_gen_add_i64(t, t1, t2);
615 static void do_vaddwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
616                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
618     static const TCGOpcode vecop_list[] = {
619         INDEX_op_shri_vec, INDEX_op_add_vec, 0
620         };
621     static const GVecGen3 op[4] = {
622         {
623             .fniv = gen_vaddwod_u,
624             .fno = gen_helper_vaddwod_h_bu,
625             .opt_opc = vecop_list,
626             .vece = MO_16
627         },
628         {
629             .fni4 = gen_vaddwod_w_hu,
630             .fniv = gen_vaddwod_u,
631             .fno = gen_helper_vaddwod_w_hu,
632             .opt_opc = vecop_list,
633             .vece = MO_32
634         },
635         {
636             .fni8 = gen_vaddwod_d_wu,
637             .fniv = gen_vaddwod_u,
638             .fno = gen_helper_vaddwod_d_wu,
639             .opt_opc = vecop_list,
640             .vece = MO_64
641         },
642         {
643             .fno = gen_helper_vaddwod_q_du,
644             .vece = MO_128
645         },
646     };
648     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
651 TRANS(vaddwod_h_bu, gvec_vvv, MO_8, do_vaddwod_u)
652 TRANS(vaddwod_w_hu, gvec_vvv, MO_16, do_vaddwod_u)
653 TRANS(vaddwod_d_wu, gvec_vvv, MO_32, do_vaddwod_u)
654 TRANS(vaddwod_q_du, gvec_vvv, MO_64, do_vaddwod_u)
656 static void gen_vsubwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
658     TCGv_vec t1, t2, t3;
660     t1 = tcg_temp_new_vec_matching(a);
661     t2 = tcg_temp_new_vec_matching(b);
662     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
663     tcg_gen_and_vec(vece, t1, a, t3);
664     tcg_gen_and_vec(vece, t2, b, t3);
665     tcg_gen_sub_vec(vece, t, t1, t2);
668 static void gen_vsubwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
670     TCGv_i32 t1, t2;
672     t1 = tcg_temp_new_i32();
673     t2 = tcg_temp_new_i32();
674     tcg_gen_ext16u_i32(t1, a);
675     tcg_gen_ext16u_i32(t2, b);
676     tcg_gen_sub_i32(t, t1, t2);
679 static void gen_vsubwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
681     TCGv_i64 t1, t2;
683     t1 = tcg_temp_new_i64();
684     t2 = tcg_temp_new_i64();
685     tcg_gen_ext32u_i64(t1, a);
686     tcg_gen_ext32u_i64(t2, b);
687     tcg_gen_sub_i64(t, t1, t2);
690 static void do_vsubwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
691                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
693     static const TCGOpcode vecop_list[] = {
694         INDEX_op_sub_vec, 0
695         };
696     static const GVecGen3 op[4] = {
697         {
698             .fniv = gen_vsubwev_u,
699             .fno = gen_helper_vsubwev_h_bu,
700             .opt_opc = vecop_list,
701             .vece = MO_16
702         },
703         {
704             .fni4 = gen_vsubwev_w_hu,
705             .fniv = gen_vsubwev_u,
706             .fno = gen_helper_vsubwev_w_hu,
707             .opt_opc = vecop_list,
708             .vece = MO_32
709         },
710         {
711             .fni8 = gen_vsubwev_d_wu,
712             .fniv = gen_vsubwev_u,
713             .fno = gen_helper_vsubwev_d_wu,
714             .opt_opc = vecop_list,
715             .vece = MO_64
716         },
717         {
718             .fno = gen_helper_vsubwev_q_du,
719             .vece = MO_128
720         },
721     };
723     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
726 TRANS(vsubwev_h_bu, gvec_vvv, MO_8, do_vsubwev_u)
727 TRANS(vsubwev_w_hu, gvec_vvv, MO_16, do_vsubwev_u)
728 TRANS(vsubwev_d_wu, gvec_vvv, MO_32, do_vsubwev_u)
729 TRANS(vsubwev_q_du, gvec_vvv, MO_64, do_vsubwev_u)
731 static void gen_vsubwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
733     TCGv_vec t1, t2;
735     int halfbits = 4 << vece;
737     t1 = tcg_temp_new_vec_matching(a);
738     t2 = tcg_temp_new_vec_matching(b);
740     /* Zero-extend the odd elements for vector */
741     tcg_gen_shri_vec(vece, t1, a, halfbits);
742     tcg_gen_shri_vec(vece, t2, b, halfbits);
744     tcg_gen_sub_vec(vece, t, t1, t2);
747 static void gen_vsubwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
749     TCGv_i32 t1, t2;
751     t1 = tcg_temp_new_i32();
752     t2 = tcg_temp_new_i32();
753     tcg_gen_shri_i32(t1, a, 16);
754     tcg_gen_shri_i32(t2, b, 16);
755     tcg_gen_sub_i32(t, t1, t2);
758 static void gen_vsubwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
760     TCGv_i64 t1, t2;
762     t1 = tcg_temp_new_i64();
763     t2 = tcg_temp_new_i64();
764     tcg_gen_shri_i64(t1, a, 32);
765     tcg_gen_shri_i64(t2, b, 32);
766     tcg_gen_sub_i64(t, t1, t2);
769 static void do_vsubwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
770                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
772     static const TCGOpcode vecop_list[] = {
773         INDEX_op_shri_vec, INDEX_op_sub_vec, 0
774         };
775     static const GVecGen3 op[4] = {
776         {
777             .fniv = gen_vsubwod_u,
778             .fno = gen_helper_vsubwod_h_bu,
779             .opt_opc = vecop_list,
780             .vece = MO_16
781         },
782         {
783             .fni4 = gen_vsubwod_w_hu,
784             .fniv = gen_vsubwod_u,
785             .fno = gen_helper_vsubwod_w_hu,
786             .opt_opc = vecop_list,
787             .vece = MO_32
788         },
789         {
790             .fni8 = gen_vsubwod_d_wu,
791             .fniv = gen_vsubwod_u,
792             .fno = gen_helper_vsubwod_d_wu,
793             .opt_opc = vecop_list,
794             .vece = MO_64
795         },
796         {
797             .fno = gen_helper_vsubwod_q_du,
798             .vece = MO_128
799         },
800     };
802     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
805 TRANS(vsubwod_h_bu, gvec_vvv, MO_8, do_vsubwod_u)
806 TRANS(vsubwod_w_hu, gvec_vvv, MO_16, do_vsubwod_u)
807 TRANS(vsubwod_d_wu, gvec_vvv, MO_32, do_vsubwod_u)
808 TRANS(vsubwod_q_du, gvec_vvv, MO_64, do_vsubwod_u)
810 static void gen_vaddwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
812     TCGv_vec t1, t2, t3;
814     int halfbits = 4 << vece;
816     t1 = tcg_temp_new_vec_matching(a);
817     t2 = tcg_temp_new_vec_matching(b);
818     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, halfbits));
820     /* Zero-extend the even elements from a */
821     tcg_gen_and_vec(vece, t1, a, t3);
823     /* Sign-extend the even elements from b */
824     tcg_gen_shli_vec(vece, t2, b, halfbits);
825     tcg_gen_sari_vec(vece, t2, t2, halfbits);
827     tcg_gen_add_vec(vece, t, t1, t2);
830 static void gen_vaddwev_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
832     TCGv_i32 t1, t2;
834     t1 = tcg_temp_new_i32();
835     t2 = tcg_temp_new_i32();
836     tcg_gen_ext16u_i32(t1, a);
837     tcg_gen_ext16s_i32(t2, b);
838     tcg_gen_add_i32(t, t1, t2);
841 static void gen_vaddwev_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
843     TCGv_i64 t1, t2;
845     t1 = tcg_temp_new_i64();
846     t2 = tcg_temp_new_i64();
847     tcg_gen_ext32u_i64(t1, a);
848     tcg_gen_ext32s_i64(t2, b);
849     tcg_gen_add_i64(t, t1, t2);
852 static void do_vaddwev_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
853                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
855     static const TCGOpcode vecop_list[] = {
856         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
857         };
858     static const GVecGen3 op[4] = {
859         {
860             .fniv = gen_vaddwev_u_s,
861             .fno = gen_helper_vaddwev_h_bu_b,
862             .opt_opc = vecop_list,
863             .vece = MO_16
864         },
865         {
866             .fni4 = gen_vaddwev_w_hu_h,
867             .fniv = gen_vaddwev_u_s,
868             .fno = gen_helper_vaddwev_w_hu_h,
869             .opt_opc = vecop_list,
870             .vece = MO_32
871         },
872         {
873             .fni8 = gen_vaddwev_d_wu_w,
874             .fniv = gen_vaddwev_u_s,
875             .fno = gen_helper_vaddwev_d_wu_w,
876             .opt_opc = vecop_list,
877             .vece = MO_64
878         },
879         {
880             .fno = gen_helper_vaddwev_q_du_d,
881             .vece = MO_128
882         },
883     };
885     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
888 TRANS(vaddwev_h_bu_b, gvec_vvv, MO_8, do_vaddwev_u_s)
889 TRANS(vaddwev_w_hu_h, gvec_vvv, MO_16, do_vaddwev_u_s)
890 TRANS(vaddwev_d_wu_w, gvec_vvv, MO_32, do_vaddwev_u_s)
891 TRANS(vaddwev_q_du_d, gvec_vvv, MO_64, do_vaddwev_u_s)
893 static void gen_vaddwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
895     TCGv_vec t1, t2;
897     int halfbits = 4 << vece;
899     t1 = tcg_temp_new_vec_matching(a);
900     t2 = tcg_temp_new_vec_matching(b);
902     /* Zero-extend the odd elements from a */
903     tcg_gen_shri_vec(vece, t1, a, halfbits);
904     /* Sign-extend the odd elements from b */
905     tcg_gen_sari_vec(vece, t2, b, halfbits);
907     tcg_gen_add_vec(vece, t, t1, t2);
910 static void gen_vaddwod_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
912     TCGv_i32 t1, t2;
914     t1 = tcg_temp_new_i32();
915     t2 = tcg_temp_new_i32();
916     tcg_gen_shri_i32(t1, a, 16);
917     tcg_gen_sari_i32(t2, b, 16);
918     tcg_gen_add_i32(t, t1, t2);
921 static void gen_vaddwod_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
923     TCGv_i64 t1, t2;
925     t1 = tcg_temp_new_i64();
926     t2 = tcg_temp_new_i64();
927     tcg_gen_shri_i64(t1, a, 32);
928     tcg_gen_sari_i64(t2, b, 32);
929     tcg_gen_add_i64(t, t1, t2);
932 static void do_vaddwod_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
933                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
935     static const TCGOpcode vecop_list[] = {
936         INDEX_op_shri_vec, INDEX_op_sari_vec,  INDEX_op_add_vec, 0
937         };
938     static const GVecGen3 op[4] = {
939         {
940             .fniv = gen_vaddwod_u_s,
941             .fno = gen_helper_vaddwod_h_bu_b,
942             .opt_opc = vecop_list,
943             .vece = MO_16
944         },
945         {
946             .fni4 = gen_vaddwod_w_hu_h,
947             .fniv = gen_vaddwod_u_s,
948             .fno = gen_helper_vaddwod_w_hu_h,
949             .opt_opc = vecop_list,
950             .vece = MO_32
951         },
952         {
953             .fni8 = gen_vaddwod_d_wu_w,
954             .fniv = gen_vaddwod_u_s,
955             .fno = gen_helper_vaddwod_d_wu_w,
956             .opt_opc = vecop_list,
957             .vece = MO_64
958         },
959         {
960             .fno = gen_helper_vaddwod_q_du_d,
961             .vece = MO_128
962         },
963     };
965     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
968 TRANS(vaddwod_h_bu_b, gvec_vvv, MO_8, do_vaddwod_u_s)
969 TRANS(vaddwod_w_hu_h, gvec_vvv, MO_16, do_vaddwod_u_s)
970 TRANS(vaddwod_d_wu_w, gvec_vvv, MO_32, do_vaddwod_u_s)
971 TRANS(vaddwod_q_du_d, gvec_vvv, MO_64, do_vaddwod_u_s)
973 static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
974                     void (*gen_shr_vec)(unsigned, TCGv_vec,
975                                         TCGv_vec, int64_t),
976                     void (*gen_round_vec)(unsigned, TCGv_vec,
977                                           TCGv_vec, TCGv_vec))
979     TCGv_vec tmp = tcg_temp_new_vec_matching(t);
980     gen_round_vec(vece, tmp, a, b);
981     tcg_gen_and_vec(vece, tmp, tmp, tcg_constant_vec_matching(t, vece, 1));
982     gen_shr_vec(vece, a, a, 1);
983     gen_shr_vec(vece, b, b, 1);
984     tcg_gen_add_vec(vece, t, a, b);
985     tcg_gen_add_vec(vece, t, t, tmp);
988 static void gen_vavg_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
990     do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_and_vec);
993 static void gen_vavg_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
995     do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_and_vec);
998 static void gen_vavgr_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1000     do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_or_vec);
1003 static void gen_vavgr_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1005     do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_or_vec);
1008 static void do_vavg_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1009                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1011     static const TCGOpcode vecop_list[] = {
1012         INDEX_op_sari_vec, INDEX_op_add_vec, 0
1013         };
1014     static const GVecGen3 op[4] = {
1015         {
1016             .fniv = gen_vavg_s,
1017             .fno = gen_helper_vavg_b,
1018             .opt_opc = vecop_list,
1019             .vece = MO_8
1020         },
1021         {
1022             .fniv = gen_vavg_s,
1023             .fno = gen_helper_vavg_h,
1024             .opt_opc = vecop_list,
1025             .vece = MO_16
1026         },
1027         {
1028             .fniv = gen_vavg_s,
1029             .fno = gen_helper_vavg_w,
1030             .opt_opc = vecop_list,
1031             .vece = MO_32
1032         },
1033         {
1034             .fniv = gen_vavg_s,
1035             .fno = gen_helper_vavg_d,
1036             .opt_opc = vecop_list,
1037             .vece = MO_64
1038         },
1039     };
1041     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1044 static void do_vavg_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1045                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1047     static const TCGOpcode vecop_list[] = {
1048         INDEX_op_shri_vec, INDEX_op_add_vec, 0
1049         };
1050     static const GVecGen3 op[4] = {
1051         {
1052             .fniv = gen_vavg_u,
1053             .fno = gen_helper_vavg_bu,
1054             .opt_opc = vecop_list,
1055             .vece = MO_8
1056         },
1057         {
1058             .fniv = gen_vavg_u,
1059             .fno = gen_helper_vavg_hu,
1060             .opt_opc = vecop_list,
1061             .vece = MO_16
1062         },
1063         {
1064             .fniv = gen_vavg_u,
1065             .fno = gen_helper_vavg_wu,
1066             .opt_opc = vecop_list,
1067             .vece = MO_32
1068         },
1069         {
1070             .fniv = gen_vavg_u,
1071             .fno = gen_helper_vavg_du,
1072             .opt_opc = vecop_list,
1073             .vece = MO_64
1074         },
1075     };
1077     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1080 TRANS(vavg_b, gvec_vvv, MO_8, do_vavg_s)
1081 TRANS(vavg_h, gvec_vvv, MO_16, do_vavg_s)
1082 TRANS(vavg_w, gvec_vvv, MO_32, do_vavg_s)
1083 TRANS(vavg_d, gvec_vvv, MO_64, do_vavg_s)
1084 TRANS(vavg_bu, gvec_vvv, MO_8, do_vavg_u)
1085 TRANS(vavg_hu, gvec_vvv, MO_16, do_vavg_u)
1086 TRANS(vavg_wu, gvec_vvv, MO_32, do_vavg_u)
1087 TRANS(vavg_du, gvec_vvv, MO_64, do_vavg_u)
1089 static void do_vavgr_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1090                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1092     static const TCGOpcode vecop_list[] = {
1093         INDEX_op_sari_vec, INDEX_op_add_vec, 0
1094         };
1095     static const GVecGen3 op[4] = {
1096         {
1097             .fniv = gen_vavgr_s,
1098             .fno = gen_helper_vavgr_b,
1099             .opt_opc = vecop_list,
1100             .vece = MO_8
1101         },
1102         {
1103             .fniv = gen_vavgr_s,
1104             .fno = gen_helper_vavgr_h,
1105             .opt_opc = vecop_list,
1106             .vece = MO_16
1107         },
1108         {
1109             .fniv = gen_vavgr_s,
1110             .fno = gen_helper_vavgr_w,
1111             .opt_opc = vecop_list,
1112             .vece = MO_32
1113         },
1114         {
1115             .fniv = gen_vavgr_s,
1116             .fno = gen_helper_vavgr_d,
1117             .opt_opc = vecop_list,
1118             .vece = MO_64
1119         },
1120     };
1122     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1125 static void do_vavgr_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1126                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1128     static const TCGOpcode vecop_list[] = {
1129         INDEX_op_shri_vec, INDEX_op_add_vec, 0
1130         };
1131     static const GVecGen3 op[4] = {
1132         {
1133             .fniv = gen_vavgr_u,
1134             .fno = gen_helper_vavgr_bu,
1135             .opt_opc = vecop_list,
1136             .vece = MO_8
1137         },
1138         {
1139             .fniv = gen_vavgr_u,
1140             .fno = gen_helper_vavgr_hu,
1141             .opt_opc = vecop_list,
1142             .vece = MO_16
1143         },
1144         {
1145             .fniv = gen_vavgr_u,
1146             .fno = gen_helper_vavgr_wu,
1147             .opt_opc = vecop_list,
1148             .vece = MO_32
1149         },
1150         {
1151             .fniv = gen_vavgr_u,
1152             .fno = gen_helper_vavgr_du,
1153             .opt_opc = vecop_list,
1154             .vece = MO_64
1155         },
1156     };
1158     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1161 TRANS(vavgr_b, gvec_vvv, MO_8, do_vavgr_s)
1162 TRANS(vavgr_h, gvec_vvv, MO_16, do_vavgr_s)
1163 TRANS(vavgr_w, gvec_vvv, MO_32, do_vavgr_s)
1164 TRANS(vavgr_d, gvec_vvv, MO_64, do_vavgr_s)
1165 TRANS(vavgr_bu, gvec_vvv, MO_8, do_vavgr_u)
1166 TRANS(vavgr_hu, gvec_vvv, MO_16, do_vavgr_u)
1167 TRANS(vavgr_wu, gvec_vvv, MO_32, do_vavgr_u)
1168 TRANS(vavgr_du, gvec_vvv, MO_64, do_vavgr_u)
1170 static void gen_vabsd_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1172     tcg_gen_smax_vec(vece, t, a, b);
1173     tcg_gen_smin_vec(vece, a, a, b);
1174     tcg_gen_sub_vec(vece, t, t, a);
1177 static void do_vabsd_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1178                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1180     static const TCGOpcode vecop_list[] = {
1181         INDEX_op_smax_vec, INDEX_op_smin_vec, INDEX_op_sub_vec, 0
1182         };
1183     static const GVecGen3 op[4] = {
1184         {
1185             .fniv = gen_vabsd_s,
1186             .fno = gen_helper_vabsd_b,
1187             .opt_opc = vecop_list,
1188             .vece = MO_8
1189         },
1190         {
1191             .fniv = gen_vabsd_s,
1192             .fno = gen_helper_vabsd_h,
1193             .opt_opc = vecop_list,
1194             .vece = MO_16
1195         },
1196         {
1197             .fniv = gen_vabsd_s,
1198             .fno = gen_helper_vabsd_w,
1199             .opt_opc = vecop_list,
1200             .vece = MO_32
1201         },
1202         {
1203             .fniv = gen_vabsd_s,
1204             .fno = gen_helper_vabsd_d,
1205             .opt_opc = vecop_list,
1206             .vece = MO_64
1207         },
1208     };
1210     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1213 static void gen_vabsd_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1215     tcg_gen_umax_vec(vece, t, a, b);
1216     tcg_gen_umin_vec(vece, a, a, b);
1217     tcg_gen_sub_vec(vece, t, t, a);
1220 static void do_vabsd_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1221                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1223     static const TCGOpcode vecop_list[] = {
1224         INDEX_op_umax_vec, INDEX_op_umin_vec, INDEX_op_sub_vec, 0
1225         };
1226     static const GVecGen3 op[4] = {
1227         {
1228             .fniv = gen_vabsd_u,
1229             .fno = gen_helper_vabsd_bu,
1230             .opt_opc = vecop_list,
1231             .vece = MO_8
1232         },
1233         {
1234             .fniv = gen_vabsd_u,
1235             .fno = gen_helper_vabsd_hu,
1236             .opt_opc = vecop_list,
1237             .vece = MO_16
1238         },
1239         {
1240             .fniv = gen_vabsd_u,
1241             .fno = gen_helper_vabsd_wu,
1242             .opt_opc = vecop_list,
1243             .vece = MO_32
1244         },
1245         {
1246             .fniv = gen_vabsd_u,
1247             .fno = gen_helper_vabsd_du,
1248             .opt_opc = vecop_list,
1249             .vece = MO_64
1250         },
1251     };
1253     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1256 TRANS(vabsd_b, gvec_vvv, MO_8, do_vabsd_s)
1257 TRANS(vabsd_h, gvec_vvv, MO_16, do_vabsd_s)
1258 TRANS(vabsd_w, gvec_vvv, MO_32, do_vabsd_s)
1259 TRANS(vabsd_d, gvec_vvv, MO_64, do_vabsd_s)
1260 TRANS(vabsd_bu, gvec_vvv, MO_8, do_vabsd_u)
1261 TRANS(vabsd_hu, gvec_vvv, MO_16, do_vabsd_u)
1262 TRANS(vabsd_wu, gvec_vvv, MO_32, do_vabsd_u)
1263 TRANS(vabsd_du, gvec_vvv, MO_64, do_vabsd_u)
1265 static void gen_vadda(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1267     TCGv_vec t1, t2;
1269     t1 = tcg_temp_new_vec_matching(a);
1270     t2 = tcg_temp_new_vec_matching(b);
1272     tcg_gen_abs_vec(vece, t1, a);
1273     tcg_gen_abs_vec(vece, t2, b);
1274     tcg_gen_add_vec(vece, t, t1, t2);
1277 static void do_vadda(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1278                      uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1280     static const TCGOpcode vecop_list[] = {
1281         INDEX_op_abs_vec, INDEX_op_add_vec, 0
1282         };
1283     static const GVecGen3 op[4] = {
1284         {
1285             .fniv = gen_vadda,
1286             .fno = gen_helper_vadda_b,
1287             .opt_opc = vecop_list,
1288             .vece = MO_8
1289         },
1290         {
1291             .fniv = gen_vadda,
1292             .fno = gen_helper_vadda_h,
1293             .opt_opc = vecop_list,
1294             .vece = MO_16
1295         },
1296         {
1297             .fniv = gen_vadda,
1298             .fno = gen_helper_vadda_w,
1299             .opt_opc = vecop_list,
1300             .vece = MO_32
1301         },
1302         {
1303             .fniv = gen_vadda,
1304             .fno = gen_helper_vadda_d,
1305             .opt_opc = vecop_list,
1306             .vece = MO_64
1307         },
1308     };
1310     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1313 TRANS(vadda_b, gvec_vvv, MO_8, do_vadda)
1314 TRANS(vadda_h, gvec_vvv, MO_16, do_vadda)
1315 TRANS(vadda_w, gvec_vvv, MO_32, do_vadda)
1316 TRANS(vadda_d, gvec_vvv, MO_64, do_vadda)
1318 TRANS(vmax_b, gvec_vvv, MO_8, tcg_gen_gvec_smax)
1319 TRANS(vmax_h, gvec_vvv, MO_16, tcg_gen_gvec_smax)
1320 TRANS(vmax_w, gvec_vvv, MO_32, tcg_gen_gvec_smax)
1321 TRANS(vmax_d, gvec_vvv, MO_64, tcg_gen_gvec_smax)
1322 TRANS(vmax_bu, gvec_vvv, MO_8, tcg_gen_gvec_umax)
1323 TRANS(vmax_hu, gvec_vvv, MO_16, tcg_gen_gvec_umax)
1324 TRANS(vmax_wu, gvec_vvv, MO_32, tcg_gen_gvec_umax)
1325 TRANS(vmax_du, gvec_vvv, MO_64, tcg_gen_gvec_umax)
1327 TRANS(vmin_b, gvec_vvv, MO_8, tcg_gen_gvec_smin)
1328 TRANS(vmin_h, gvec_vvv, MO_16, tcg_gen_gvec_smin)
1329 TRANS(vmin_w, gvec_vvv, MO_32, tcg_gen_gvec_smin)
1330 TRANS(vmin_d, gvec_vvv, MO_64, tcg_gen_gvec_smin)
1331 TRANS(vmin_bu, gvec_vvv, MO_8, tcg_gen_gvec_umin)
1332 TRANS(vmin_hu, gvec_vvv, MO_16, tcg_gen_gvec_umin)
1333 TRANS(vmin_wu, gvec_vvv, MO_32, tcg_gen_gvec_umin)
1334 TRANS(vmin_du, gvec_vvv, MO_64, tcg_gen_gvec_umin)
1336 static void gen_vmini_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1338     tcg_gen_smin_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1341 static void gen_vmini_u(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1343     tcg_gen_umin_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1346 static void gen_vmaxi_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1348     tcg_gen_smax_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1351 static void gen_vmaxi_u(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1353     tcg_gen_umax_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1356 static void do_vmini_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1357                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1359     static const TCGOpcode vecop_list[] = {
1360         INDEX_op_smin_vec, 0
1361         };
1362     static const GVecGen2i op[4] = {
1363         {
1364             .fniv = gen_vmini_s,
1365             .fnoi = gen_helper_vmini_b,
1366             .opt_opc = vecop_list,
1367             .vece = MO_8
1368         },
1369         {
1370             .fniv = gen_vmini_s,
1371             .fnoi = gen_helper_vmini_h,
1372             .opt_opc = vecop_list,
1373             .vece = MO_16
1374         },
1375         {
1376             .fniv = gen_vmini_s,
1377             .fnoi = gen_helper_vmini_w,
1378             .opt_opc = vecop_list,
1379             .vece = MO_32
1380         },
1381         {
1382             .fniv = gen_vmini_s,
1383             .fnoi = gen_helper_vmini_d,
1384             .opt_opc = vecop_list,
1385             .vece = MO_64
1386         },
1387     };
1389     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1392 static void do_vmini_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1393                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1395     static const TCGOpcode vecop_list[] = {
1396         INDEX_op_umin_vec, 0
1397         };
1398     static const GVecGen2i op[4] = {
1399         {
1400             .fniv = gen_vmini_u,
1401             .fnoi = gen_helper_vmini_bu,
1402             .opt_opc = vecop_list,
1403             .vece = MO_8
1404         },
1405         {
1406             .fniv = gen_vmini_u,
1407             .fnoi = gen_helper_vmini_hu,
1408             .opt_opc = vecop_list,
1409             .vece = MO_16
1410         },
1411         {
1412             .fniv = gen_vmini_u,
1413             .fnoi = gen_helper_vmini_wu,
1414             .opt_opc = vecop_list,
1415             .vece = MO_32
1416         },
1417         {
1418             .fniv = gen_vmini_u,
1419             .fnoi = gen_helper_vmini_du,
1420             .opt_opc = vecop_list,
1421             .vece = MO_64
1422         },
1423     };
1425     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1428 TRANS(vmini_b, gvec_vv_i, MO_8, do_vmini_s)
1429 TRANS(vmini_h, gvec_vv_i, MO_16, do_vmini_s)
1430 TRANS(vmini_w, gvec_vv_i, MO_32, do_vmini_s)
1431 TRANS(vmini_d, gvec_vv_i, MO_64, do_vmini_s)
1432 TRANS(vmini_bu, gvec_vv_i, MO_8, do_vmini_u)
1433 TRANS(vmini_hu, gvec_vv_i, MO_16, do_vmini_u)
1434 TRANS(vmini_wu, gvec_vv_i, MO_32, do_vmini_u)
1435 TRANS(vmini_du, gvec_vv_i, MO_64, do_vmini_u)
1437 static void do_vmaxi_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1438                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1440     static const TCGOpcode vecop_list[] = {
1441         INDEX_op_smax_vec, 0
1442         };
1443     static const GVecGen2i op[4] = {
1444         {
1445             .fniv = gen_vmaxi_s,
1446             .fnoi = gen_helper_vmaxi_b,
1447             .opt_opc = vecop_list,
1448             .vece = MO_8
1449         },
1450         {
1451             .fniv = gen_vmaxi_s,
1452             .fnoi = gen_helper_vmaxi_h,
1453             .opt_opc = vecop_list,
1454             .vece = MO_16
1455         },
1456         {
1457             .fniv = gen_vmaxi_s,
1458             .fnoi = gen_helper_vmaxi_w,
1459             .opt_opc = vecop_list,
1460             .vece = MO_32
1461         },
1462         {
1463             .fniv = gen_vmaxi_s,
1464             .fnoi = gen_helper_vmaxi_d,
1465             .opt_opc = vecop_list,
1466             .vece = MO_64
1467         },
1468     };
1470     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1473 static void do_vmaxi_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1474                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1476     static const TCGOpcode vecop_list[] = {
1477         INDEX_op_umax_vec, 0
1478         };
1479     static const GVecGen2i op[4] = {
1480         {
1481             .fniv = gen_vmaxi_u,
1482             .fnoi = gen_helper_vmaxi_bu,
1483             .opt_opc = vecop_list,
1484             .vece = MO_8
1485         },
1486         {
1487             .fniv = gen_vmaxi_u,
1488             .fnoi = gen_helper_vmaxi_hu,
1489             .opt_opc = vecop_list,
1490             .vece = MO_16
1491         },
1492         {
1493             .fniv = gen_vmaxi_u,
1494             .fnoi = gen_helper_vmaxi_wu,
1495             .opt_opc = vecop_list,
1496             .vece = MO_32
1497         },
1498         {
1499             .fniv = gen_vmaxi_u,
1500             .fnoi = gen_helper_vmaxi_du,
1501             .opt_opc = vecop_list,
1502             .vece = MO_64
1503         },
1504     };
1506     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1509 TRANS(vmaxi_b, gvec_vv_i, MO_8, do_vmaxi_s)
1510 TRANS(vmaxi_h, gvec_vv_i, MO_16, do_vmaxi_s)
1511 TRANS(vmaxi_w, gvec_vv_i, MO_32, do_vmaxi_s)
1512 TRANS(vmaxi_d, gvec_vv_i, MO_64, do_vmaxi_s)
1513 TRANS(vmaxi_bu, gvec_vv_i, MO_8, do_vmaxi_u)
1514 TRANS(vmaxi_hu, gvec_vv_i, MO_16, do_vmaxi_u)
1515 TRANS(vmaxi_wu, gvec_vv_i, MO_32, do_vmaxi_u)
1516 TRANS(vmaxi_du, gvec_vv_i, MO_64, do_vmaxi_u)