target/loongarch: Implement xvadd/xvsub
[qemu/ar7.git] / target / loongarch / insn_trans / trans_vec.c.inc
blob3252e1d8091565b15e03720b8b38970c31361d04
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * LoongArch vector translate functions
4  * Copyright (c) 2022-2023 Loongson Technology Corporation Limited
5  */
7 #ifndef CONFIG_USER_ONLY
9 static bool check_vec(DisasContext *ctx, uint32_t oprsz)
11     if ((oprsz == 16) && ((ctx->base.tb->flags & HW_FLAGS_EUEN_SXE) == 0)) {
12         generate_exception(ctx, EXCCODE_SXD);
13         return false;
14     }
16     if ((oprsz == 32) && ((ctx->base.tb->flags & HW_FLAGS_EUEN_ASXE) == 0)) {
17         generate_exception(ctx, EXCCODE_ASXD);
18         return false;
19     }
21     return true;
24 #else
26 static bool check_vec(DisasContext *ctx, uint32_t oprsz)
28     return true;
31 #endif
33 static bool gen_vvvv_ptr_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
34                             gen_helper_gvec_4_ptr *fn)
36     tcg_gen_gvec_4_ptr(vec_full_offset(a->vd),
37                        vec_full_offset(a->vj),
38                        vec_full_offset(a->vk),
39                        vec_full_offset(a->va),
40                        cpu_env,
41                        oprsz, ctx->vl / 8, 0, fn);
42     return true;
45 static bool gen_vvvv_ptr(DisasContext *ctx, arg_vvvv *a,
46                          gen_helper_gvec_4_ptr *fn)
48     if (!check_vec(ctx, 16)) {
49         return true;
50     }
52     return gen_vvvv_ptr_vl(ctx, a, 16, fn);
55 static bool gen_vvvv_vl(DisasContext *ctx, arg_vvvv *a, uint32_t oprsz,
56                         gen_helper_gvec_4 *fn)
58     tcg_gen_gvec_4_ool(vec_full_offset(a->vd),
59                        vec_full_offset(a->vj),
60                        vec_full_offset(a->vk),
61                        vec_full_offset(a->va),
62                        oprsz, ctx->vl / 8, 0, fn);
63     return true;
66 static bool gen_vvvv(DisasContext *ctx, arg_vvvv *a,
67                      gen_helper_gvec_4 *fn)
69     if (!check_vec(ctx, 16)) {
70         return true;
71     }
73     return gen_vvvv_vl(ctx, a, 16, fn);
76 static bool gen_vvv_ptr_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
77                            gen_helper_gvec_3_ptr *fn)
79     tcg_gen_gvec_3_ptr(vec_full_offset(a->vd),
80                        vec_full_offset(a->vj),
81                        vec_full_offset(a->vk),
82                        cpu_env,
83                        oprsz, ctx->vl / 8, 0, fn);
84     return true;
87 static bool gen_vvv_ptr(DisasContext *ctx, arg_vvv *a,
88                         gen_helper_gvec_3_ptr *fn)
90     if (!check_vec(ctx, 16)) {
91         return true;
92     }
94     return gen_vvv_ptr_vl(ctx, a, 16, fn);
97 static bool gen_vvv_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
98                        gen_helper_gvec_3 *fn)
100     tcg_gen_gvec_3_ool(vec_full_offset(a->vd),
101                        vec_full_offset(a->vj),
102                        vec_full_offset(a->vk),
103                        oprsz, ctx->vl / 8, 0, fn);
104     return true;
107 static bool gen_vvv(DisasContext *ctx, arg_vvv *a, gen_helper_gvec_3 *fn)
109     if (!check_vec(ctx, 16)) {
110         return true;
111     }
113     return gen_vvv_vl(ctx, a, 16, fn);
116 static bool gen_vv_ptr_vl(DisasContext *ctx, arg_vv *a, uint32_t oprsz,
117                           gen_helper_gvec_2_ptr *fn)
119     tcg_gen_gvec_2_ptr(vec_full_offset(a->vd),
120                        vec_full_offset(a->vj),
121                        cpu_env,
122                        oprsz, ctx->vl / 8, 0, fn);
123     return true;
126 static bool gen_vv_ptr(DisasContext *ctx, arg_vv *a,
127                        gen_helper_gvec_2_ptr *fn)
129     if (!check_vec(ctx, 16)) {
130         return true;
131     }
133     return gen_vv_ptr_vl(ctx, a, 16, fn);
136 static bool gen_vv_vl(DisasContext *ctx, arg_vv *a, uint32_t oprsz,
137                       gen_helper_gvec_2 *fn)
139     tcg_gen_gvec_2_ool(vec_full_offset(a->vd),
140                        vec_full_offset(a->vj),
141                        oprsz, ctx->vl / 8, 0, fn);
142     return true;
145 static bool gen_vv(DisasContext *ctx, arg_vv *a, gen_helper_gvec_2 *fn)
147     if (!check_vec(ctx, 16)) {
148         return true;
149     }
151     return gen_vv_vl(ctx, a, 16, fn);
154 static bool gen_vv_i_vl(DisasContext *ctx, arg_vv_i *a, uint32_t oprsz,
155                         gen_helper_gvec_2i *fn)
157     tcg_gen_gvec_2i_ool(vec_full_offset(a->vd),
158                         vec_full_offset(a->vj),
159                         tcg_constant_i64(a->imm),
160                         oprsz, ctx->vl / 8, 0, fn);
161     return true;
164 static bool gen_vv_i(DisasContext *ctx, arg_vv_i *a, gen_helper_gvec_2i *fn)
166     if (!check_vec(ctx, 16)) {
167         return true;
168     }
170     return gen_vv_i_vl(ctx, a, 16, fn);
173 static bool gen_cv(DisasContext *ctx, arg_cv *a,
174                     void (*func)(TCGv_ptr, TCGv_i32, TCGv_i32))
176     TCGv_i32 vj = tcg_constant_i32(a->vj);
177     TCGv_i32 cd = tcg_constant_i32(a->cd);
179     if (!check_vec(ctx, 16)) {
180         return true;
181     }
183     func(cpu_env, cd, vj);
184     return true;
187 static bool gvec_vvv_vl(DisasContext *ctx, arg_vvv *a,
188                         uint32_t oprsz, MemOp mop,
189                         void (*func)(unsigned, uint32_t, uint32_t,
190                                      uint32_t, uint32_t, uint32_t))
192     uint32_t vd_ofs = vec_full_offset(a->vd);
193     uint32_t vj_ofs = vec_full_offset(a->vj);
194     uint32_t vk_ofs = vec_full_offset(a->vk);
196     if (!check_vec(ctx, oprsz)) {
197         return true;
198     }
200     func(mop, vd_ofs, vj_ofs, vk_ofs, oprsz, ctx->vl / 8);
201     return true;
204 static bool gvec_vvv(DisasContext *ctx, arg_vvv *a, MemOp mop,
205                      void (*func)(unsigned, uint32_t, uint32_t,
206                                   uint32_t, uint32_t, uint32_t))
208     return gvec_vvv_vl(ctx, a, 16, mop, func);
211 static bool gvec_xxx(DisasContext *ctx, arg_vvv *a, MemOp mop,
212                      void (*func)(unsigned, uint32_t, uint32_t,
213                                   uint32_t, uint32_t, uint32_t))
215     return gvec_vvv_vl(ctx, a, 32, mop, func);
218 static bool gvec_vv_vl(DisasContext *ctx, arg_vv *a,
219                        uint32_t oprsz, MemOp mop,
220                        void (*func)(unsigned, uint32_t, uint32_t,
221                                     uint32_t, uint32_t))
223     uint32_t vd_ofs = vec_full_offset(a->vd);
224     uint32_t vj_ofs = vec_full_offset(a->vj);
226     func(mop, vd_ofs, vj_ofs, oprsz, ctx->vl / 8);
227     return true;
231 static bool gvec_vv(DisasContext *ctx, arg_vv *a, MemOp mop,
232                     void (*func)(unsigned, uint32_t, uint32_t,
233                                  uint32_t, uint32_t))
235     if (!check_vec(ctx, 16)) {
236         return true;
237     }
239     return gvec_vv_vl(ctx, a, 16, mop, func);
242 static bool gvec_vv_i_vl(DisasContext *ctx, arg_vv_i *a,
243                          uint32_t oprsz, MemOp mop,
244                          void (*func)(unsigned, uint32_t, uint32_t,
245                                       int64_t, uint32_t, uint32_t))
247     uint32_t vd_ofs = vec_full_offset(a->vd);
248     uint32_t vj_ofs = vec_full_offset(a->vj);
250     func(mop, vd_ofs, vj_ofs, a->imm, oprsz, ctx->vl / 8);
251     return true;
254 static bool gvec_vv_i(DisasContext *ctx, arg_vv_i *a, MemOp mop,
255                       void (*func)(unsigned, uint32_t, uint32_t,
256                                    int64_t, uint32_t, uint32_t))
258     if (!check_vec(ctx, 16)) {
259         return true;
260     }
262     return gvec_vv_i_vl(ctx, a, 16, mop, func);
265 static bool gvec_subi_vl(DisasContext *ctx, arg_vv_i *a,
266                          uint32_t oprsz, MemOp mop)
268     uint32_t vd_ofs = vec_full_offset(a->vd);
269     uint32_t vj_ofs = vec_full_offset(a->vj);
271     tcg_gen_gvec_addi(mop, vd_ofs, vj_ofs, -a->imm, oprsz, ctx->vl / 8);
272     return true;
275 static bool gvec_subi(DisasContext *ctx, arg_vv_i *a, MemOp mop)
277     if (!check_vec(ctx, 16)) {
278         return true;
279     }
281     return gvec_subi_vl(ctx, a, 16, mop);
284 TRANS(vadd_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_add)
285 TRANS(vadd_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_add)
286 TRANS(vadd_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_add)
287 TRANS(vadd_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_add)
288 TRANS(xvadd_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_add)
289 TRANS(xvadd_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_add)
290 TRANS(xvadd_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_add)
291 TRANS(xvadd_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_add)
293 static bool gen_vaddsub_q_vl(DisasContext *ctx, arg_vvv *a, uint32_t oprsz,
294                              void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
295                                           TCGv_i64, TCGv_i64, TCGv_i64))
297     int i;
298     TCGv_i64 rh, rl, ah, al, bh, bl;
300     if (!check_vec(ctx, oprsz)) {
301         return true;
302     }
304     rh = tcg_temp_new_i64();
305     rl = tcg_temp_new_i64();
306     ah = tcg_temp_new_i64();
307     al = tcg_temp_new_i64();
308     bh = tcg_temp_new_i64();
309     bl = tcg_temp_new_i64();
311     for (i = 0; i < oprsz / 16; i++) {
312         get_vreg64(ah, a->vj, 1 + i * 2);
313         get_vreg64(al, a->vj, i * 2);
314         get_vreg64(bh, a->vk, 1 + i * 2);
315         get_vreg64(bl, a->vk, i * 2);
317         func(rl, rh, al, ah, bl, bh);
319         set_vreg64(rh, a->vd, 1 + i * 2);
320         set_vreg64(rl, a->vd, i * 2);
321     }
322     return true;
325 static bool gen_vaddsub_q(DisasContext *ctx, arg_vvv *a,
326                           void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
327                                        TCGv_i64, TCGv_i64, TCGv_i64))
329     return gen_vaddsub_q_vl(ctx, a, 16, func);
332 static bool gen_xvaddsub_q(DisasContext *ctx, arg_vvv *a,
333                            void (*func)(TCGv_i64, TCGv_i64, TCGv_i64,
334                                         TCGv_i64, TCGv_i64, TCGv_i64))
336     return gen_vaddsub_q_vl(ctx, a, 32, func);
339 TRANS(vsub_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_sub)
340 TRANS(vsub_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_sub)
341 TRANS(vsub_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_sub)
342 TRANS(vsub_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_sub)
343 TRANS(xvsub_b, LASX, gvec_xxx, MO_8, tcg_gen_gvec_sub)
344 TRANS(xvsub_h, LASX, gvec_xxx, MO_16, tcg_gen_gvec_sub)
345 TRANS(xvsub_w, LASX, gvec_xxx, MO_32, tcg_gen_gvec_sub)
346 TRANS(xvsub_d, LASX, gvec_xxx, MO_64, tcg_gen_gvec_sub)
348 TRANS(vadd_q, LSX, gen_vaddsub_q, tcg_gen_add2_i64)
349 TRANS(vsub_q, LSX, gen_vaddsub_q, tcg_gen_sub2_i64)
350 TRANS(xvadd_q, LASX, gen_xvaddsub_q, tcg_gen_add2_i64)
351 TRANS(xvsub_q, LASX, gen_xvaddsub_q, tcg_gen_sub2_i64)
353 TRANS(vaddi_bu, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_addi)
354 TRANS(vaddi_hu, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_addi)
355 TRANS(vaddi_wu, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_addi)
356 TRANS(vaddi_du, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_addi)
357 TRANS(vsubi_bu, LSX, gvec_subi, MO_8)
358 TRANS(vsubi_hu, LSX, gvec_subi, MO_16)
359 TRANS(vsubi_wu, LSX, gvec_subi, MO_32)
360 TRANS(vsubi_du, LSX, gvec_subi, MO_64)
362 TRANS(vneg_b, LSX, gvec_vv, MO_8, tcg_gen_gvec_neg)
363 TRANS(vneg_h, LSX, gvec_vv, MO_16, tcg_gen_gvec_neg)
364 TRANS(vneg_w, LSX, gvec_vv, MO_32, tcg_gen_gvec_neg)
365 TRANS(vneg_d, LSX, gvec_vv, MO_64, tcg_gen_gvec_neg)
367 TRANS(vsadd_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_ssadd)
368 TRANS(vsadd_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_ssadd)
369 TRANS(vsadd_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_ssadd)
370 TRANS(vsadd_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_ssadd)
371 TRANS(vsadd_bu, LSX, gvec_vvv, MO_8, tcg_gen_gvec_usadd)
372 TRANS(vsadd_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_usadd)
373 TRANS(vsadd_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_usadd)
374 TRANS(vsadd_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_usadd)
375 TRANS(vssub_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_sssub)
376 TRANS(vssub_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_sssub)
377 TRANS(vssub_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_sssub)
378 TRANS(vssub_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_sssub)
379 TRANS(vssub_bu, LSX, gvec_vvv, MO_8, tcg_gen_gvec_ussub)
380 TRANS(vssub_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_ussub)
381 TRANS(vssub_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_ussub)
382 TRANS(vssub_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_ussub)
384 TRANS(vhaddw_h_b, LSX, gen_vvv, gen_helper_vhaddw_h_b)
385 TRANS(vhaddw_w_h, LSX, gen_vvv, gen_helper_vhaddw_w_h)
386 TRANS(vhaddw_d_w, LSX, gen_vvv, gen_helper_vhaddw_d_w)
387 TRANS(vhaddw_q_d, LSX, gen_vvv, gen_helper_vhaddw_q_d)
388 TRANS(vhaddw_hu_bu, LSX, gen_vvv, gen_helper_vhaddw_hu_bu)
389 TRANS(vhaddw_wu_hu, LSX, gen_vvv, gen_helper_vhaddw_wu_hu)
390 TRANS(vhaddw_du_wu, LSX, gen_vvv, gen_helper_vhaddw_du_wu)
391 TRANS(vhaddw_qu_du, LSX, gen_vvv, gen_helper_vhaddw_qu_du)
392 TRANS(vhsubw_h_b, LSX, gen_vvv, gen_helper_vhsubw_h_b)
393 TRANS(vhsubw_w_h, LSX, gen_vvv, gen_helper_vhsubw_w_h)
394 TRANS(vhsubw_d_w, LSX, gen_vvv, gen_helper_vhsubw_d_w)
395 TRANS(vhsubw_q_d, LSX, gen_vvv, gen_helper_vhsubw_q_d)
396 TRANS(vhsubw_hu_bu, LSX, gen_vvv, gen_helper_vhsubw_hu_bu)
397 TRANS(vhsubw_wu_hu, LSX, gen_vvv, gen_helper_vhsubw_wu_hu)
398 TRANS(vhsubw_du_wu, LSX, gen_vvv, gen_helper_vhsubw_du_wu)
399 TRANS(vhsubw_qu_du, LSX, gen_vvv, gen_helper_vhsubw_qu_du)
401 static void gen_vaddwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
403     TCGv_vec t1, t2;
405     int halfbits = 4 << vece;
407     t1 = tcg_temp_new_vec_matching(a);
408     t2 = tcg_temp_new_vec_matching(b);
410     /* Sign-extend the even elements from a */
411     tcg_gen_shli_vec(vece, t1, a, halfbits);
412     tcg_gen_sari_vec(vece, t1, t1, halfbits);
414     /* Sign-extend the even elements from b */
415     tcg_gen_shli_vec(vece, t2, b, halfbits);
416     tcg_gen_sari_vec(vece, t2, t2, halfbits);
418     tcg_gen_add_vec(vece, t, t1, t2);
421 static void gen_vaddwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
423     TCGv_i32 t1, t2;
425     t1 = tcg_temp_new_i32();
426     t2 = tcg_temp_new_i32();
427     tcg_gen_ext16s_i32(t1, a);
428     tcg_gen_ext16s_i32(t2, b);
429     tcg_gen_add_i32(t, t1, t2);
432 static void gen_vaddwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
434     TCGv_i64 t1, t2;
436     t1 = tcg_temp_new_i64();
437     t2 = tcg_temp_new_i64();
438     tcg_gen_ext32s_i64(t1, a);
439     tcg_gen_ext32s_i64(t2, b);
440     tcg_gen_add_i64(t, t1, t2);
443 static void do_vaddwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
444                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
446     static const TCGOpcode vecop_list[] = {
447         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
448         };
449     static const GVecGen3 op[4] = {
450         {
451             .fniv = gen_vaddwev_s,
452             .fno = gen_helper_vaddwev_h_b,
453             .opt_opc = vecop_list,
454             .vece = MO_16
455         },
456         {
457             .fni4 = gen_vaddwev_w_h,
458             .fniv = gen_vaddwev_s,
459             .fno = gen_helper_vaddwev_w_h,
460             .opt_opc = vecop_list,
461             .vece = MO_32
462         },
463         {
464             .fni8 = gen_vaddwev_d_w,
465             .fniv = gen_vaddwev_s,
466             .fno = gen_helper_vaddwev_d_w,
467             .opt_opc = vecop_list,
468             .vece = MO_64
469         },
470         {
471             .fno = gen_helper_vaddwev_q_d,
472             .vece = MO_128
473         },
474     };
476     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
479 TRANS(vaddwev_h_b, LSX, gvec_vvv, MO_8, do_vaddwev_s)
480 TRANS(vaddwev_w_h, LSX, gvec_vvv, MO_16, do_vaddwev_s)
481 TRANS(vaddwev_d_w, LSX, gvec_vvv, MO_32, do_vaddwev_s)
482 TRANS(vaddwev_q_d, LSX, gvec_vvv, MO_64, do_vaddwev_s)
484 static void gen_vaddwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
486     TCGv_i32 t1, t2;
488     t1 = tcg_temp_new_i32();
489     t2 = tcg_temp_new_i32();
490     tcg_gen_sari_i32(t1, a, 16);
491     tcg_gen_sari_i32(t2, b, 16);
492     tcg_gen_add_i32(t, t1, t2);
495 static void gen_vaddwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
497     TCGv_i64 t1, t2;
499     t1 = tcg_temp_new_i64();
500     t2 = tcg_temp_new_i64();
501     tcg_gen_sari_i64(t1, a, 32);
502     tcg_gen_sari_i64(t2, b, 32);
503     tcg_gen_add_i64(t, t1, t2);
506 static void gen_vaddwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
508     TCGv_vec t1, t2;
510     int halfbits = 4 << vece;
512     t1 = tcg_temp_new_vec_matching(a);
513     t2 = tcg_temp_new_vec_matching(b);
515     /* Sign-extend the odd elements for vector */
516     tcg_gen_sari_vec(vece, t1, a, halfbits);
517     tcg_gen_sari_vec(vece, t2, b, halfbits);
519     tcg_gen_add_vec(vece, t, t1, t2);
522 static void do_vaddwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
523                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
525     static const TCGOpcode vecop_list[] = {
526         INDEX_op_sari_vec, INDEX_op_add_vec, 0
527         };
528     static const GVecGen3 op[4] = {
529         {
530             .fniv = gen_vaddwod_s,
531             .fno = gen_helper_vaddwod_h_b,
532             .opt_opc = vecop_list,
533             .vece = MO_16
534         },
535         {
536             .fni4 = gen_vaddwod_w_h,
537             .fniv = gen_vaddwod_s,
538             .fno = gen_helper_vaddwod_w_h,
539             .opt_opc = vecop_list,
540             .vece = MO_32
541         },
542         {
543             .fni8 = gen_vaddwod_d_w,
544             .fniv = gen_vaddwod_s,
545             .fno = gen_helper_vaddwod_d_w,
546             .opt_opc = vecop_list,
547             .vece = MO_64
548         },
549         {
550             .fno = gen_helper_vaddwod_q_d,
551             .vece = MO_128
552         },
553     };
555     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
558 TRANS(vaddwod_h_b, LSX, gvec_vvv, MO_8, do_vaddwod_s)
559 TRANS(vaddwod_w_h, LSX, gvec_vvv, MO_16, do_vaddwod_s)
560 TRANS(vaddwod_d_w, LSX, gvec_vvv, MO_32, do_vaddwod_s)
561 TRANS(vaddwod_q_d, LSX, gvec_vvv, MO_64, do_vaddwod_s)
563 static void gen_vsubwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
565     TCGv_vec t1, t2;
567     int halfbits = 4 << vece;
569     t1 = tcg_temp_new_vec_matching(a);
570     t2 = tcg_temp_new_vec_matching(b);
572     /* Sign-extend the even elements from a */
573     tcg_gen_shli_vec(vece, t1, a, halfbits);
574     tcg_gen_sari_vec(vece, t1, t1, halfbits);
576     /* Sign-extend the even elements from b */
577     tcg_gen_shli_vec(vece, t2, b, halfbits);
578     tcg_gen_sari_vec(vece, t2, t2, halfbits);
580     tcg_gen_sub_vec(vece, t, t1, t2);
583 static void gen_vsubwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
585     TCGv_i32 t1, t2;
587     t1 = tcg_temp_new_i32();
588     t2 = tcg_temp_new_i32();
589     tcg_gen_ext16s_i32(t1, a);
590     tcg_gen_ext16s_i32(t2, b);
591     tcg_gen_sub_i32(t, t1, t2);
594 static void gen_vsubwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
596     TCGv_i64 t1, t2;
598     t1 = tcg_temp_new_i64();
599     t2 = tcg_temp_new_i64();
600     tcg_gen_ext32s_i64(t1, a);
601     tcg_gen_ext32s_i64(t2, b);
602     tcg_gen_sub_i64(t, t1, t2);
605 static void do_vsubwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
606                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
608     static const TCGOpcode vecop_list[] = {
609         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_sub_vec, 0
610         };
611     static const GVecGen3 op[4] = {
612         {
613             .fniv = gen_vsubwev_s,
614             .fno = gen_helper_vsubwev_h_b,
615             .opt_opc = vecop_list,
616             .vece = MO_16
617         },
618         {
619             .fni4 = gen_vsubwev_w_h,
620             .fniv = gen_vsubwev_s,
621             .fno = gen_helper_vsubwev_w_h,
622             .opt_opc = vecop_list,
623             .vece = MO_32
624         },
625         {
626             .fni8 = gen_vsubwev_d_w,
627             .fniv = gen_vsubwev_s,
628             .fno = gen_helper_vsubwev_d_w,
629             .opt_opc = vecop_list,
630             .vece = MO_64
631         },
632         {
633             .fno = gen_helper_vsubwev_q_d,
634             .vece = MO_128
635         },
636     };
638     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
641 TRANS(vsubwev_h_b, LSX, gvec_vvv, MO_8, do_vsubwev_s)
642 TRANS(vsubwev_w_h, LSX, gvec_vvv, MO_16, do_vsubwev_s)
643 TRANS(vsubwev_d_w, LSX, gvec_vvv, MO_32, do_vsubwev_s)
644 TRANS(vsubwev_q_d, LSX, gvec_vvv, MO_64, do_vsubwev_s)
646 static void gen_vsubwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
648     TCGv_vec t1, t2;
650     int halfbits = 4 << vece;
652     t1 = tcg_temp_new_vec_matching(a);
653     t2 = tcg_temp_new_vec_matching(b);
655     /* Sign-extend the odd elements for vector */
656     tcg_gen_sari_vec(vece, t1, a, halfbits);
657     tcg_gen_sari_vec(vece, t2, b, halfbits);
659     tcg_gen_sub_vec(vece, t, t1, t2);
662 static void gen_vsubwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
664     TCGv_i32 t1, t2;
666     t1 = tcg_temp_new_i32();
667     t2 = tcg_temp_new_i32();
668     tcg_gen_sari_i32(t1, a, 16);
669     tcg_gen_sari_i32(t2, b, 16);
670     tcg_gen_sub_i32(t, t1, t2);
673 static void gen_vsubwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
675     TCGv_i64 t1, t2;
677     t1 = tcg_temp_new_i64();
678     t2 = tcg_temp_new_i64();
679     tcg_gen_sari_i64(t1, a, 32);
680     tcg_gen_sari_i64(t2, b, 32);
681     tcg_gen_sub_i64(t, t1, t2);
684 static void do_vsubwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
685                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
687     static const TCGOpcode vecop_list[] = {
688         INDEX_op_sari_vec, INDEX_op_sub_vec, 0
689         };
690     static const GVecGen3 op[4] = {
691         {
692             .fniv = gen_vsubwod_s,
693             .fno = gen_helper_vsubwod_h_b,
694             .opt_opc = vecop_list,
695             .vece = MO_16
696         },
697         {
698             .fni4 = gen_vsubwod_w_h,
699             .fniv = gen_vsubwod_s,
700             .fno = gen_helper_vsubwod_w_h,
701             .opt_opc = vecop_list,
702             .vece = MO_32
703         },
704         {
705             .fni8 = gen_vsubwod_d_w,
706             .fniv = gen_vsubwod_s,
707             .fno = gen_helper_vsubwod_d_w,
708             .opt_opc = vecop_list,
709             .vece = MO_64
710         },
711         {
712             .fno = gen_helper_vsubwod_q_d,
713             .vece = MO_128
714         },
715     };
717     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
720 TRANS(vsubwod_h_b, LSX, gvec_vvv, MO_8, do_vsubwod_s)
721 TRANS(vsubwod_w_h, LSX, gvec_vvv, MO_16, do_vsubwod_s)
722 TRANS(vsubwod_d_w, LSX, gvec_vvv, MO_32, do_vsubwod_s)
723 TRANS(vsubwod_q_d, LSX, gvec_vvv, MO_64, do_vsubwod_s)
725 static void gen_vaddwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
727     TCGv_vec t1, t2, t3;
729     t1 = tcg_temp_new_vec_matching(a);
730     t2 = tcg_temp_new_vec_matching(b);
731     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
732     tcg_gen_and_vec(vece, t1, a, t3);
733     tcg_gen_and_vec(vece, t2, b, t3);
734     tcg_gen_add_vec(vece, t, t1, t2);
737 static void gen_vaddwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
739     TCGv_i32 t1, t2;
741     t1 = tcg_temp_new_i32();
742     t2 = tcg_temp_new_i32();
743     tcg_gen_ext16u_i32(t1, a);
744     tcg_gen_ext16u_i32(t2, b);
745     tcg_gen_add_i32(t, t1, t2);
748 static void gen_vaddwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
750     TCGv_i64 t1, t2;
752     t1 = tcg_temp_new_i64();
753     t2 = tcg_temp_new_i64();
754     tcg_gen_ext32u_i64(t1, a);
755     tcg_gen_ext32u_i64(t2, b);
756     tcg_gen_add_i64(t, t1, t2);
759 static void do_vaddwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
760                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
762     static const TCGOpcode vecop_list[] = {
763         INDEX_op_add_vec, 0
764         };
765     static const GVecGen3 op[4] = {
766         {
767             .fniv = gen_vaddwev_u,
768             .fno = gen_helper_vaddwev_h_bu,
769             .opt_opc = vecop_list,
770             .vece = MO_16
771         },
772         {
773             .fni4 = gen_vaddwev_w_hu,
774             .fniv = gen_vaddwev_u,
775             .fno = gen_helper_vaddwev_w_hu,
776             .opt_opc = vecop_list,
777             .vece = MO_32
778         },
779         {
780             .fni8 = gen_vaddwev_d_wu,
781             .fniv = gen_vaddwev_u,
782             .fno = gen_helper_vaddwev_d_wu,
783             .opt_opc = vecop_list,
784             .vece = MO_64
785         },
786         {
787             .fno = gen_helper_vaddwev_q_du,
788             .vece = MO_128
789         },
790     };
792     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
795 TRANS(vaddwev_h_bu, LSX, gvec_vvv, MO_8, do_vaddwev_u)
796 TRANS(vaddwev_w_hu, LSX, gvec_vvv, MO_16, do_vaddwev_u)
797 TRANS(vaddwev_d_wu, LSX, gvec_vvv, MO_32, do_vaddwev_u)
798 TRANS(vaddwev_q_du, LSX, gvec_vvv, MO_64, do_vaddwev_u)
800 static void gen_vaddwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
802     TCGv_vec t1, t2;
804     int halfbits = 4 << vece;
806     t1 = tcg_temp_new_vec_matching(a);
807     t2 = tcg_temp_new_vec_matching(b);
809     /* Zero-extend the odd elements for vector */
810     tcg_gen_shri_vec(vece, t1, a, halfbits);
811     tcg_gen_shri_vec(vece, t2, b, halfbits);
813     tcg_gen_add_vec(vece, t, t1, t2);
816 static void gen_vaddwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
818     TCGv_i32 t1, t2;
820     t1 = tcg_temp_new_i32();
821     t2 = tcg_temp_new_i32();
822     tcg_gen_shri_i32(t1, a, 16);
823     tcg_gen_shri_i32(t2, b, 16);
824     tcg_gen_add_i32(t, t1, t2);
827 static void gen_vaddwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
829     TCGv_i64 t1, t2;
831     t1 = tcg_temp_new_i64();
832     t2 = tcg_temp_new_i64();
833     tcg_gen_shri_i64(t1, a, 32);
834     tcg_gen_shri_i64(t2, b, 32);
835     tcg_gen_add_i64(t, t1, t2);
838 static void do_vaddwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
839                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
841     static const TCGOpcode vecop_list[] = {
842         INDEX_op_shri_vec, INDEX_op_add_vec, 0
843         };
844     static const GVecGen3 op[4] = {
845         {
846             .fniv = gen_vaddwod_u,
847             .fno = gen_helper_vaddwod_h_bu,
848             .opt_opc = vecop_list,
849             .vece = MO_16
850         },
851         {
852             .fni4 = gen_vaddwod_w_hu,
853             .fniv = gen_vaddwod_u,
854             .fno = gen_helper_vaddwod_w_hu,
855             .opt_opc = vecop_list,
856             .vece = MO_32
857         },
858         {
859             .fni8 = gen_vaddwod_d_wu,
860             .fniv = gen_vaddwod_u,
861             .fno = gen_helper_vaddwod_d_wu,
862             .opt_opc = vecop_list,
863             .vece = MO_64
864         },
865         {
866             .fno = gen_helper_vaddwod_q_du,
867             .vece = MO_128
868         },
869     };
871     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
874 TRANS(vaddwod_h_bu, LSX, gvec_vvv, MO_8, do_vaddwod_u)
875 TRANS(vaddwod_w_hu, LSX, gvec_vvv, MO_16, do_vaddwod_u)
876 TRANS(vaddwod_d_wu, LSX, gvec_vvv, MO_32, do_vaddwod_u)
877 TRANS(vaddwod_q_du, LSX, gvec_vvv, MO_64, do_vaddwod_u)
879 static void gen_vsubwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
881     TCGv_vec t1, t2, t3;
883     t1 = tcg_temp_new_vec_matching(a);
884     t2 = tcg_temp_new_vec_matching(b);
885     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
886     tcg_gen_and_vec(vece, t1, a, t3);
887     tcg_gen_and_vec(vece, t2, b, t3);
888     tcg_gen_sub_vec(vece, t, t1, t2);
891 static void gen_vsubwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
893     TCGv_i32 t1, t2;
895     t1 = tcg_temp_new_i32();
896     t2 = tcg_temp_new_i32();
897     tcg_gen_ext16u_i32(t1, a);
898     tcg_gen_ext16u_i32(t2, b);
899     tcg_gen_sub_i32(t, t1, t2);
902 static void gen_vsubwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
904     TCGv_i64 t1, t2;
906     t1 = tcg_temp_new_i64();
907     t2 = tcg_temp_new_i64();
908     tcg_gen_ext32u_i64(t1, a);
909     tcg_gen_ext32u_i64(t2, b);
910     tcg_gen_sub_i64(t, t1, t2);
913 static void do_vsubwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
914                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
916     static const TCGOpcode vecop_list[] = {
917         INDEX_op_sub_vec, 0
918         };
919     static const GVecGen3 op[4] = {
920         {
921             .fniv = gen_vsubwev_u,
922             .fno = gen_helper_vsubwev_h_bu,
923             .opt_opc = vecop_list,
924             .vece = MO_16
925         },
926         {
927             .fni4 = gen_vsubwev_w_hu,
928             .fniv = gen_vsubwev_u,
929             .fno = gen_helper_vsubwev_w_hu,
930             .opt_opc = vecop_list,
931             .vece = MO_32
932         },
933         {
934             .fni8 = gen_vsubwev_d_wu,
935             .fniv = gen_vsubwev_u,
936             .fno = gen_helper_vsubwev_d_wu,
937             .opt_opc = vecop_list,
938             .vece = MO_64
939         },
940         {
941             .fno = gen_helper_vsubwev_q_du,
942             .vece = MO_128
943         },
944     };
946     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
949 TRANS(vsubwev_h_bu, LSX, gvec_vvv, MO_8, do_vsubwev_u)
950 TRANS(vsubwev_w_hu, LSX, gvec_vvv, MO_16, do_vsubwev_u)
951 TRANS(vsubwev_d_wu, LSX, gvec_vvv, MO_32, do_vsubwev_u)
952 TRANS(vsubwev_q_du, LSX, gvec_vvv, MO_64, do_vsubwev_u)
954 static void gen_vsubwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
956     TCGv_vec t1, t2;
958     int halfbits = 4 << vece;
960     t1 = tcg_temp_new_vec_matching(a);
961     t2 = tcg_temp_new_vec_matching(b);
963     /* Zero-extend the odd elements for vector */
964     tcg_gen_shri_vec(vece, t1, a, halfbits);
965     tcg_gen_shri_vec(vece, t2, b, halfbits);
967     tcg_gen_sub_vec(vece, t, t1, t2);
970 static void gen_vsubwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
972     TCGv_i32 t1, t2;
974     t1 = tcg_temp_new_i32();
975     t2 = tcg_temp_new_i32();
976     tcg_gen_shri_i32(t1, a, 16);
977     tcg_gen_shri_i32(t2, b, 16);
978     tcg_gen_sub_i32(t, t1, t2);
981 static void gen_vsubwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
983     TCGv_i64 t1, t2;
985     t1 = tcg_temp_new_i64();
986     t2 = tcg_temp_new_i64();
987     tcg_gen_shri_i64(t1, a, 32);
988     tcg_gen_shri_i64(t2, b, 32);
989     tcg_gen_sub_i64(t, t1, t2);
992 static void do_vsubwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
993                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
995     static const TCGOpcode vecop_list[] = {
996         INDEX_op_shri_vec, INDEX_op_sub_vec, 0
997         };
998     static const GVecGen3 op[4] = {
999         {
1000             .fniv = gen_vsubwod_u,
1001             .fno = gen_helper_vsubwod_h_bu,
1002             .opt_opc = vecop_list,
1003             .vece = MO_16
1004         },
1005         {
1006             .fni4 = gen_vsubwod_w_hu,
1007             .fniv = gen_vsubwod_u,
1008             .fno = gen_helper_vsubwod_w_hu,
1009             .opt_opc = vecop_list,
1010             .vece = MO_32
1011         },
1012         {
1013             .fni8 = gen_vsubwod_d_wu,
1014             .fniv = gen_vsubwod_u,
1015             .fno = gen_helper_vsubwod_d_wu,
1016             .opt_opc = vecop_list,
1017             .vece = MO_64
1018         },
1019         {
1020             .fno = gen_helper_vsubwod_q_du,
1021             .vece = MO_128
1022         },
1023     };
1025     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1028 TRANS(vsubwod_h_bu, LSX, gvec_vvv, MO_8, do_vsubwod_u)
1029 TRANS(vsubwod_w_hu, LSX, gvec_vvv, MO_16, do_vsubwod_u)
1030 TRANS(vsubwod_d_wu, LSX, gvec_vvv, MO_32, do_vsubwod_u)
1031 TRANS(vsubwod_q_du, LSX, gvec_vvv, MO_64, do_vsubwod_u)
1033 static void gen_vaddwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1035     TCGv_vec t1, t2, t3;
1037     int halfbits = 4 << vece;
1039     t1 = tcg_temp_new_vec_matching(a);
1040     t2 = tcg_temp_new_vec_matching(b);
1041     t3 = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, halfbits));
1043     /* Zero-extend the even elements from a */
1044     tcg_gen_and_vec(vece, t1, a, t3);
1046     /* Sign-extend the even elements from b */
1047     tcg_gen_shli_vec(vece, t2, b, halfbits);
1048     tcg_gen_sari_vec(vece, t2, t2, halfbits);
1050     tcg_gen_add_vec(vece, t, t1, t2);
1053 static void gen_vaddwev_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1055     TCGv_i32 t1, t2;
1057     t1 = tcg_temp_new_i32();
1058     t2 = tcg_temp_new_i32();
1059     tcg_gen_ext16u_i32(t1, a);
1060     tcg_gen_ext16s_i32(t2, b);
1061     tcg_gen_add_i32(t, t1, t2);
1064 static void gen_vaddwev_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1066     TCGv_i64 t1, t2;
1068     t1 = tcg_temp_new_i64();
1069     t2 = tcg_temp_new_i64();
1070     tcg_gen_ext32u_i64(t1, a);
1071     tcg_gen_ext32s_i64(t2, b);
1072     tcg_gen_add_i64(t, t1, t2);
1075 static void do_vaddwev_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1076                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1078     static const TCGOpcode vecop_list[] = {
1079         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
1080         };
1081     static const GVecGen3 op[4] = {
1082         {
1083             .fniv = gen_vaddwev_u_s,
1084             .fno = gen_helper_vaddwev_h_bu_b,
1085             .opt_opc = vecop_list,
1086             .vece = MO_16
1087         },
1088         {
1089             .fni4 = gen_vaddwev_w_hu_h,
1090             .fniv = gen_vaddwev_u_s,
1091             .fno = gen_helper_vaddwev_w_hu_h,
1092             .opt_opc = vecop_list,
1093             .vece = MO_32
1094         },
1095         {
1096             .fni8 = gen_vaddwev_d_wu_w,
1097             .fniv = gen_vaddwev_u_s,
1098             .fno = gen_helper_vaddwev_d_wu_w,
1099             .opt_opc = vecop_list,
1100             .vece = MO_64
1101         },
1102         {
1103             .fno = gen_helper_vaddwev_q_du_d,
1104             .vece = MO_128
1105         },
1106     };
1108     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1111 TRANS(vaddwev_h_bu_b, LSX, gvec_vvv, MO_8, do_vaddwev_u_s)
1112 TRANS(vaddwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vaddwev_u_s)
1113 TRANS(vaddwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vaddwev_u_s)
1114 TRANS(vaddwev_q_du_d, LSX, gvec_vvv, MO_64, do_vaddwev_u_s)
1116 static void gen_vaddwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1118     TCGv_vec t1, t2;
1120     int halfbits = 4 << vece;
1122     t1 = tcg_temp_new_vec_matching(a);
1123     t2 = tcg_temp_new_vec_matching(b);
1125     /* Zero-extend the odd elements from a */
1126     tcg_gen_shri_vec(vece, t1, a, halfbits);
1127     /* Sign-extend the odd elements from b */
1128     tcg_gen_sari_vec(vece, t2, b, halfbits);
1130     tcg_gen_add_vec(vece, t, t1, t2);
1133 static void gen_vaddwod_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1135     TCGv_i32 t1, t2;
1137     t1 = tcg_temp_new_i32();
1138     t2 = tcg_temp_new_i32();
1139     tcg_gen_shri_i32(t1, a, 16);
1140     tcg_gen_sari_i32(t2, b, 16);
1141     tcg_gen_add_i32(t, t1, t2);
1144 static void gen_vaddwod_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1146     TCGv_i64 t1, t2;
1148     t1 = tcg_temp_new_i64();
1149     t2 = tcg_temp_new_i64();
1150     tcg_gen_shri_i64(t1, a, 32);
1151     tcg_gen_sari_i64(t2, b, 32);
1152     tcg_gen_add_i64(t, t1, t2);
1155 static void do_vaddwod_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1156                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1158     static const TCGOpcode vecop_list[] = {
1159         INDEX_op_shri_vec, INDEX_op_sari_vec,  INDEX_op_add_vec, 0
1160         };
1161     static const GVecGen3 op[4] = {
1162         {
1163             .fniv = gen_vaddwod_u_s,
1164             .fno = gen_helper_vaddwod_h_bu_b,
1165             .opt_opc = vecop_list,
1166             .vece = MO_16
1167         },
1168         {
1169             .fni4 = gen_vaddwod_w_hu_h,
1170             .fniv = gen_vaddwod_u_s,
1171             .fno = gen_helper_vaddwod_w_hu_h,
1172             .opt_opc = vecop_list,
1173             .vece = MO_32
1174         },
1175         {
1176             .fni8 = gen_vaddwod_d_wu_w,
1177             .fniv = gen_vaddwod_u_s,
1178             .fno = gen_helper_vaddwod_d_wu_w,
1179             .opt_opc = vecop_list,
1180             .vece = MO_64
1181         },
1182         {
1183             .fno = gen_helper_vaddwod_q_du_d,
1184             .vece = MO_128
1185         },
1186     };
1188     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1191 TRANS(vaddwod_h_bu_b, LSX, gvec_vvv, MO_8, do_vaddwod_u_s)
1192 TRANS(vaddwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vaddwod_u_s)
1193 TRANS(vaddwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vaddwod_u_s)
1194 TRANS(vaddwod_q_du_d, LSX, gvec_vvv, MO_64, do_vaddwod_u_s)
1196 static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
1197                     void (*gen_shr_vec)(unsigned, TCGv_vec,
1198                                         TCGv_vec, int64_t),
1199                     void (*gen_round_vec)(unsigned, TCGv_vec,
1200                                           TCGv_vec, TCGv_vec))
1202     TCGv_vec tmp = tcg_temp_new_vec_matching(t);
1203     gen_round_vec(vece, tmp, a, b);
1204     tcg_gen_and_vec(vece, tmp, tmp, tcg_constant_vec_matching(t, vece, 1));
1205     gen_shr_vec(vece, a, a, 1);
1206     gen_shr_vec(vece, b, b, 1);
1207     tcg_gen_add_vec(vece, t, a, b);
1208     tcg_gen_add_vec(vece, t, t, tmp);
1211 static void gen_vavg_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1213     do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_and_vec);
1216 static void gen_vavg_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1218     do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_and_vec);
1221 static void gen_vavgr_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1223     do_vavg(vece, t, a, b, tcg_gen_sari_vec, tcg_gen_or_vec);
1226 static void gen_vavgr_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1228     do_vavg(vece, t, a, b, tcg_gen_shri_vec, tcg_gen_or_vec);
1231 static void do_vavg_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1232                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1234     static const TCGOpcode vecop_list[] = {
1235         INDEX_op_sari_vec, INDEX_op_add_vec, 0
1236         };
1237     static const GVecGen3 op[4] = {
1238         {
1239             .fniv = gen_vavg_s,
1240             .fno = gen_helper_vavg_b,
1241             .opt_opc = vecop_list,
1242             .vece = MO_8
1243         },
1244         {
1245             .fniv = gen_vavg_s,
1246             .fno = gen_helper_vavg_h,
1247             .opt_opc = vecop_list,
1248             .vece = MO_16
1249         },
1250         {
1251             .fniv = gen_vavg_s,
1252             .fno = gen_helper_vavg_w,
1253             .opt_opc = vecop_list,
1254             .vece = MO_32
1255         },
1256         {
1257             .fniv = gen_vavg_s,
1258             .fno = gen_helper_vavg_d,
1259             .opt_opc = vecop_list,
1260             .vece = MO_64
1261         },
1262     };
1264     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1267 static void do_vavg_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1268                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1270     static const TCGOpcode vecop_list[] = {
1271         INDEX_op_shri_vec, INDEX_op_add_vec, 0
1272         };
1273     static const GVecGen3 op[4] = {
1274         {
1275             .fniv = gen_vavg_u,
1276             .fno = gen_helper_vavg_bu,
1277             .opt_opc = vecop_list,
1278             .vece = MO_8
1279         },
1280         {
1281             .fniv = gen_vavg_u,
1282             .fno = gen_helper_vavg_hu,
1283             .opt_opc = vecop_list,
1284             .vece = MO_16
1285         },
1286         {
1287             .fniv = gen_vavg_u,
1288             .fno = gen_helper_vavg_wu,
1289             .opt_opc = vecop_list,
1290             .vece = MO_32
1291         },
1292         {
1293             .fniv = gen_vavg_u,
1294             .fno = gen_helper_vavg_du,
1295             .opt_opc = vecop_list,
1296             .vece = MO_64
1297         },
1298     };
1300     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1303 TRANS(vavg_b, LSX, gvec_vvv, MO_8, do_vavg_s)
1304 TRANS(vavg_h, LSX, gvec_vvv, MO_16, do_vavg_s)
1305 TRANS(vavg_w, LSX, gvec_vvv, MO_32, do_vavg_s)
1306 TRANS(vavg_d, LSX, gvec_vvv, MO_64, do_vavg_s)
1307 TRANS(vavg_bu, LSX, gvec_vvv, MO_8, do_vavg_u)
1308 TRANS(vavg_hu, LSX, gvec_vvv, MO_16, do_vavg_u)
1309 TRANS(vavg_wu, LSX, gvec_vvv, MO_32, do_vavg_u)
1310 TRANS(vavg_du, LSX, gvec_vvv, MO_64, do_vavg_u)
1312 static void do_vavgr_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1313                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1315     static const TCGOpcode vecop_list[] = {
1316         INDEX_op_sari_vec, INDEX_op_add_vec, 0
1317         };
1318     static const GVecGen3 op[4] = {
1319         {
1320             .fniv = gen_vavgr_s,
1321             .fno = gen_helper_vavgr_b,
1322             .opt_opc = vecop_list,
1323             .vece = MO_8
1324         },
1325         {
1326             .fniv = gen_vavgr_s,
1327             .fno = gen_helper_vavgr_h,
1328             .opt_opc = vecop_list,
1329             .vece = MO_16
1330         },
1331         {
1332             .fniv = gen_vavgr_s,
1333             .fno = gen_helper_vavgr_w,
1334             .opt_opc = vecop_list,
1335             .vece = MO_32
1336         },
1337         {
1338             .fniv = gen_vavgr_s,
1339             .fno = gen_helper_vavgr_d,
1340             .opt_opc = vecop_list,
1341             .vece = MO_64
1342         },
1343     };
1345     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1348 static void do_vavgr_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1349                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1351     static const TCGOpcode vecop_list[] = {
1352         INDEX_op_shri_vec, INDEX_op_add_vec, 0
1353         };
1354     static const GVecGen3 op[4] = {
1355         {
1356             .fniv = gen_vavgr_u,
1357             .fno = gen_helper_vavgr_bu,
1358             .opt_opc = vecop_list,
1359             .vece = MO_8
1360         },
1361         {
1362             .fniv = gen_vavgr_u,
1363             .fno = gen_helper_vavgr_hu,
1364             .opt_opc = vecop_list,
1365             .vece = MO_16
1366         },
1367         {
1368             .fniv = gen_vavgr_u,
1369             .fno = gen_helper_vavgr_wu,
1370             .opt_opc = vecop_list,
1371             .vece = MO_32
1372         },
1373         {
1374             .fniv = gen_vavgr_u,
1375             .fno = gen_helper_vavgr_du,
1376             .opt_opc = vecop_list,
1377             .vece = MO_64
1378         },
1379     };
1381     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1384 TRANS(vavgr_b, LSX, gvec_vvv, MO_8, do_vavgr_s)
1385 TRANS(vavgr_h, LSX, gvec_vvv, MO_16, do_vavgr_s)
1386 TRANS(vavgr_w, LSX, gvec_vvv, MO_32, do_vavgr_s)
1387 TRANS(vavgr_d, LSX, gvec_vvv, MO_64, do_vavgr_s)
1388 TRANS(vavgr_bu, LSX, gvec_vvv, MO_8, do_vavgr_u)
1389 TRANS(vavgr_hu, LSX, gvec_vvv, MO_16, do_vavgr_u)
1390 TRANS(vavgr_wu, LSX, gvec_vvv, MO_32, do_vavgr_u)
1391 TRANS(vavgr_du, LSX, gvec_vvv, MO_64, do_vavgr_u)
1393 static void gen_vabsd_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1395     tcg_gen_smax_vec(vece, t, a, b);
1396     tcg_gen_smin_vec(vece, a, a, b);
1397     tcg_gen_sub_vec(vece, t, t, a);
1400 static void do_vabsd_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1401                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1403     static const TCGOpcode vecop_list[] = {
1404         INDEX_op_smax_vec, INDEX_op_smin_vec, INDEX_op_sub_vec, 0
1405         };
1406     static const GVecGen3 op[4] = {
1407         {
1408             .fniv = gen_vabsd_s,
1409             .fno = gen_helper_vabsd_b,
1410             .opt_opc = vecop_list,
1411             .vece = MO_8
1412         },
1413         {
1414             .fniv = gen_vabsd_s,
1415             .fno = gen_helper_vabsd_h,
1416             .opt_opc = vecop_list,
1417             .vece = MO_16
1418         },
1419         {
1420             .fniv = gen_vabsd_s,
1421             .fno = gen_helper_vabsd_w,
1422             .opt_opc = vecop_list,
1423             .vece = MO_32
1424         },
1425         {
1426             .fniv = gen_vabsd_s,
1427             .fno = gen_helper_vabsd_d,
1428             .opt_opc = vecop_list,
1429             .vece = MO_64
1430         },
1431     };
1433     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1436 static void gen_vabsd_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1438     tcg_gen_umax_vec(vece, t, a, b);
1439     tcg_gen_umin_vec(vece, a, a, b);
1440     tcg_gen_sub_vec(vece, t, t, a);
1443 static void do_vabsd_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1444                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1446     static const TCGOpcode vecop_list[] = {
1447         INDEX_op_umax_vec, INDEX_op_umin_vec, INDEX_op_sub_vec, 0
1448         };
1449     static const GVecGen3 op[4] = {
1450         {
1451             .fniv = gen_vabsd_u,
1452             .fno = gen_helper_vabsd_bu,
1453             .opt_opc = vecop_list,
1454             .vece = MO_8
1455         },
1456         {
1457             .fniv = gen_vabsd_u,
1458             .fno = gen_helper_vabsd_hu,
1459             .opt_opc = vecop_list,
1460             .vece = MO_16
1461         },
1462         {
1463             .fniv = gen_vabsd_u,
1464             .fno = gen_helper_vabsd_wu,
1465             .opt_opc = vecop_list,
1466             .vece = MO_32
1467         },
1468         {
1469             .fniv = gen_vabsd_u,
1470             .fno = gen_helper_vabsd_du,
1471             .opt_opc = vecop_list,
1472             .vece = MO_64
1473         },
1474     };
1476     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1479 TRANS(vabsd_b, LSX, gvec_vvv, MO_8, do_vabsd_s)
1480 TRANS(vabsd_h, LSX, gvec_vvv, MO_16, do_vabsd_s)
1481 TRANS(vabsd_w, LSX, gvec_vvv, MO_32, do_vabsd_s)
1482 TRANS(vabsd_d, LSX, gvec_vvv, MO_64, do_vabsd_s)
1483 TRANS(vabsd_bu, LSX, gvec_vvv, MO_8, do_vabsd_u)
1484 TRANS(vabsd_hu, LSX, gvec_vvv, MO_16, do_vabsd_u)
1485 TRANS(vabsd_wu, LSX, gvec_vvv, MO_32, do_vabsd_u)
1486 TRANS(vabsd_du, LSX, gvec_vvv, MO_64, do_vabsd_u)
1488 static void gen_vadda(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1490     TCGv_vec t1, t2;
1492     t1 = tcg_temp_new_vec_matching(a);
1493     t2 = tcg_temp_new_vec_matching(b);
1495     tcg_gen_abs_vec(vece, t1, a);
1496     tcg_gen_abs_vec(vece, t2, b);
1497     tcg_gen_add_vec(vece, t, t1, t2);
1500 static void do_vadda(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1501                      uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1503     static const TCGOpcode vecop_list[] = {
1504         INDEX_op_abs_vec, INDEX_op_add_vec, 0
1505         };
1506     static const GVecGen3 op[4] = {
1507         {
1508             .fniv = gen_vadda,
1509             .fno = gen_helper_vadda_b,
1510             .opt_opc = vecop_list,
1511             .vece = MO_8
1512         },
1513         {
1514             .fniv = gen_vadda,
1515             .fno = gen_helper_vadda_h,
1516             .opt_opc = vecop_list,
1517             .vece = MO_16
1518         },
1519         {
1520             .fniv = gen_vadda,
1521             .fno = gen_helper_vadda_w,
1522             .opt_opc = vecop_list,
1523             .vece = MO_32
1524         },
1525         {
1526             .fniv = gen_vadda,
1527             .fno = gen_helper_vadda_d,
1528             .opt_opc = vecop_list,
1529             .vece = MO_64
1530         },
1531     };
1533     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1536 TRANS(vadda_b, LSX, gvec_vvv, MO_8, do_vadda)
1537 TRANS(vadda_h, LSX, gvec_vvv, MO_16, do_vadda)
1538 TRANS(vadda_w, LSX, gvec_vvv, MO_32, do_vadda)
1539 TRANS(vadda_d, LSX, gvec_vvv, MO_64, do_vadda)
1541 TRANS(vmax_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_smax)
1542 TRANS(vmax_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_smax)
1543 TRANS(vmax_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_smax)
1544 TRANS(vmax_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_smax)
1545 TRANS(vmax_bu, LSX, gvec_vvv, MO_8, tcg_gen_gvec_umax)
1546 TRANS(vmax_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_umax)
1547 TRANS(vmax_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_umax)
1548 TRANS(vmax_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_umax)
1550 TRANS(vmin_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_smin)
1551 TRANS(vmin_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_smin)
1552 TRANS(vmin_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_smin)
1553 TRANS(vmin_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_smin)
1554 TRANS(vmin_bu, LSX, gvec_vvv, MO_8, tcg_gen_gvec_umin)
1555 TRANS(vmin_hu, LSX, gvec_vvv, MO_16, tcg_gen_gvec_umin)
1556 TRANS(vmin_wu, LSX, gvec_vvv, MO_32, tcg_gen_gvec_umin)
1557 TRANS(vmin_du, LSX, gvec_vvv, MO_64, tcg_gen_gvec_umin)
1559 static void gen_vmini_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1561     tcg_gen_smin_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1564 static void gen_vmini_u(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1566     tcg_gen_umin_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1569 static void gen_vmaxi_s(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1571     tcg_gen_smax_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1574 static void gen_vmaxi_u(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
1576     tcg_gen_umax_vec(vece, t, a, tcg_constant_vec_matching(t, vece, imm));
1579 static void do_vmini_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1580                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1582     static const TCGOpcode vecop_list[] = {
1583         INDEX_op_smin_vec, 0
1584         };
1585     static const GVecGen2i op[4] = {
1586         {
1587             .fniv = gen_vmini_s,
1588             .fnoi = gen_helper_vmini_b,
1589             .opt_opc = vecop_list,
1590             .vece = MO_8
1591         },
1592         {
1593             .fniv = gen_vmini_s,
1594             .fnoi = gen_helper_vmini_h,
1595             .opt_opc = vecop_list,
1596             .vece = MO_16
1597         },
1598         {
1599             .fniv = gen_vmini_s,
1600             .fnoi = gen_helper_vmini_w,
1601             .opt_opc = vecop_list,
1602             .vece = MO_32
1603         },
1604         {
1605             .fniv = gen_vmini_s,
1606             .fnoi = gen_helper_vmini_d,
1607             .opt_opc = vecop_list,
1608             .vece = MO_64
1609         },
1610     };
1612     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1615 static void do_vmini_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1616                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1618     static const TCGOpcode vecop_list[] = {
1619         INDEX_op_umin_vec, 0
1620         };
1621     static const GVecGen2i op[4] = {
1622         {
1623             .fniv = gen_vmini_u,
1624             .fnoi = gen_helper_vmini_bu,
1625             .opt_opc = vecop_list,
1626             .vece = MO_8
1627         },
1628         {
1629             .fniv = gen_vmini_u,
1630             .fnoi = gen_helper_vmini_hu,
1631             .opt_opc = vecop_list,
1632             .vece = MO_16
1633         },
1634         {
1635             .fniv = gen_vmini_u,
1636             .fnoi = gen_helper_vmini_wu,
1637             .opt_opc = vecop_list,
1638             .vece = MO_32
1639         },
1640         {
1641             .fniv = gen_vmini_u,
1642             .fnoi = gen_helper_vmini_du,
1643             .opt_opc = vecop_list,
1644             .vece = MO_64
1645         },
1646     };
1648     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1651 TRANS(vmini_b, LSX, gvec_vv_i, MO_8, do_vmini_s)
1652 TRANS(vmini_h, LSX, gvec_vv_i, MO_16, do_vmini_s)
1653 TRANS(vmini_w, LSX, gvec_vv_i, MO_32, do_vmini_s)
1654 TRANS(vmini_d, LSX, gvec_vv_i, MO_64, do_vmini_s)
1655 TRANS(vmini_bu, LSX, gvec_vv_i, MO_8, do_vmini_u)
1656 TRANS(vmini_hu, LSX, gvec_vv_i, MO_16, do_vmini_u)
1657 TRANS(vmini_wu, LSX, gvec_vv_i, MO_32, do_vmini_u)
1658 TRANS(vmini_du, LSX, gvec_vv_i, MO_64, do_vmini_u)
1660 static void do_vmaxi_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1661                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1663     static const TCGOpcode vecop_list[] = {
1664         INDEX_op_smax_vec, 0
1665         };
1666     static const GVecGen2i op[4] = {
1667         {
1668             .fniv = gen_vmaxi_s,
1669             .fnoi = gen_helper_vmaxi_b,
1670             .opt_opc = vecop_list,
1671             .vece = MO_8
1672         },
1673         {
1674             .fniv = gen_vmaxi_s,
1675             .fnoi = gen_helper_vmaxi_h,
1676             .opt_opc = vecop_list,
1677             .vece = MO_16
1678         },
1679         {
1680             .fniv = gen_vmaxi_s,
1681             .fnoi = gen_helper_vmaxi_w,
1682             .opt_opc = vecop_list,
1683             .vece = MO_32
1684         },
1685         {
1686             .fniv = gen_vmaxi_s,
1687             .fnoi = gen_helper_vmaxi_d,
1688             .opt_opc = vecop_list,
1689             .vece = MO_64
1690         },
1691     };
1693     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1696 static void do_vmaxi_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1697                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
1699     static const TCGOpcode vecop_list[] = {
1700         INDEX_op_umax_vec, 0
1701         };
1702     static const GVecGen2i op[4] = {
1703         {
1704             .fniv = gen_vmaxi_u,
1705             .fnoi = gen_helper_vmaxi_bu,
1706             .opt_opc = vecop_list,
1707             .vece = MO_8
1708         },
1709         {
1710             .fniv = gen_vmaxi_u,
1711             .fnoi = gen_helper_vmaxi_hu,
1712             .opt_opc = vecop_list,
1713             .vece = MO_16
1714         },
1715         {
1716             .fniv = gen_vmaxi_u,
1717             .fnoi = gen_helper_vmaxi_wu,
1718             .opt_opc = vecop_list,
1719             .vece = MO_32
1720         },
1721         {
1722             .fniv = gen_vmaxi_u,
1723             .fnoi = gen_helper_vmaxi_du,
1724             .opt_opc = vecop_list,
1725             .vece = MO_64
1726         },
1727     };
1729     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
1732 TRANS(vmaxi_b, LSX, gvec_vv_i, MO_8, do_vmaxi_s)
1733 TRANS(vmaxi_h, LSX, gvec_vv_i, MO_16, do_vmaxi_s)
1734 TRANS(vmaxi_w, LSX, gvec_vv_i, MO_32, do_vmaxi_s)
1735 TRANS(vmaxi_d, LSX, gvec_vv_i, MO_64, do_vmaxi_s)
1736 TRANS(vmaxi_bu, LSX, gvec_vv_i, MO_8, do_vmaxi_u)
1737 TRANS(vmaxi_hu, LSX, gvec_vv_i, MO_16, do_vmaxi_u)
1738 TRANS(vmaxi_wu, LSX, gvec_vv_i, MO_32, do_vmaxi_u)
1739 TRANS(vmaxi_du, LSX, gvec_vv_i, MO_64, do_vmaxi_u)
1741 TRANS(vmul_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_mul)
1742 TRANS(vmul_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_mul)
1743 TRANS(vmul_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_mul)
1744 TRANS(vmul_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_mul)
1746 static void gen_vmuh_w(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1748     TCGv_i32 discard = tcg_temp_new_i32();
1749     tcg_gen_muls2_i32(discard, t, a, b);
1752 static void gen_vmuh_d(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1754     TCGv_i64 discard = tcg_temp_new_i64();
1755     tcg_gen_muls2_i64(discard, t, a, b);
1758 static void do_vmuh_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1759                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1761     static const GVecGen3 op[4] = {
1762         {
1763             .fno = gen_helper_vmuh_b,
1764             .vece = MO_8
1765         },
1766         {
1767             .fno = gen_helper_vmuh_h,
1768             .vece = MO_16
1769         },
1770         {
1771             .fni4 = gen_vmuh_w,
1772             .fno = gen_helper_vmuh_w,
1773             .vece = MO_32
1774         },
1775         {
1776             .fni8 = gen_vmuh_d,
1777             .fno = gen_helper_vmuh_d,
1778             .vece = MO_64
1779         },
1780     };
1782     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1785 TRANS(vmuh_b, LSX, gvec_vvv, MO_8, do_vmuh_s)
1786 TRANS(vmuh_h, LSX, gvec_vvv, MO_16, do_vmuh_s)
1787 TRANS(vmuh_w, LSX, gvec_vvv, MO_32, do_vmuh_s)
1788 TRANS(vmuh_d, LSX, gvec_vvv, MO_64, do_vmuh_s)
1790 static void gen_vmuh_wu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1792     TCGv_i32 discard = tcg_temp_new_i32();
1793     tcg_gen_mulu2_i32(discard, t, a, b);
1796 static void gen_vmuh_du(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1798     TCGv_i64 discard = tcg_temp_new_i64();
1799     tcg_gen_mulu2_i64(discard, t, a, b);
1802 static void do_vmuh_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1803                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1805     static const GVecGen3 op[4] = {
1806         {
1807             .fno = gen_helper_vmuh_bu,
1808             .vece = MO_8
1809         },
1810         {
1811             .fno = gen_helper_vmuh_hu,
1812             .vece = MO_16
1813         },
1814         {
1815             .fni4 = gen_vmuh_wu,
1816             .fno = gen_helper_vmuh_wu,
1817             .vece = MO_32
1818         },
1819         {
1820             .fni8 = gen_vmuh_du,
1821             .fno = gen_helper_vmuh_du,
1822             .vece = MO_64
1823         },
1824     };
1826     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1829 TRANS(vmuh_bu, LSX, gvec_vvv, MO_8,  do_vmuh_u)
1830 TRANS(vmuh_hu, LSX, gvec_vvv, MO_16, do_vmuh_u)
1831 TRANS(vmuh_wu, LSX, gvec_vvv, MO_32, do_vmuh_u)
1832 TRANS(vmuh_du, LSX, gvec_vvv, MO_64, do_vmuh_u)
1834 static void gen_vmulwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1836     TCGv_vec t1, t2;
1837     int halfbits = 4 << vece;
1839     t1 = tcg_temp_new_vec_matching(a);
1840     t2 = tcg_temp_new_vec_matching(b);
1841     tcg_gen_shli_vec(vece, t1, a, halfbits);
1842     tcg_gen_sari_vec(vece, t1, t1, halfbits);
1843     tcg_gen_shli_vec(vece, t2, b, halfbits);
1844     tcg_gen_sari_vec(vece, t2, t2, halfbits);
1845     tcg_gen_mul_vec(vece, t, t1, t2);
1848 static void gen_vmulwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1850     TCGv_i32 t1, t2;
1852     t1 = tcg_temp_new_i32();
1853     t2 = tcg_temp_new_i32();
1854     tcg_gen_ext16s_i32(t1, a);
1855     tcg_gen_ext16s_i32(t2, b);
1856     tcg_gen_mul_i32(t, t1, t2);
1859 static void gen_vmulwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1861     TCGv_i64 t1, t2;
1863     t1 = tcg_temp_new_i64();
1864     t2 = tcg_temp_new_i64();
1865     tcg_gen_ext32s_i64(t1, a);
1866     tcg_gen_ext32s_i64(t2, b);
1867     tcg_gen_mul_i64(t, t1, t2);
1870 static void do_vmulwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1871                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1873     static const TCGOpcode vecop_list[] = {
1874         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_mul_vec, 0
1875         };
1876     static const GVecGen3 op[3] = {
1877         {
1878             .fniv = gen_vmulwev_s,
1879             .fno = gen_helper_vmulwev_h_b,
1880             .opt_opc = vecop_list,
1881             .vece = MO_16
1882         },
1883         {
1884             .fni4 = gen_vmulwev_w_h,
1885             .fniv = gen_vmulwev_s,
1886             .fno = gen_helper_vmulwev_w_h,
1887             .opt_opc = vecop_list,
1888             .vece = MO_32
1889         },
1890         {
1891             .fni8 = gen_vmulwev_d_w,
1892             .fniv = gen_vmulwev_s,
1893             .fno = gen_helper_vmulwev_d_w,
1894             .opt_opc = vecop_list,
1895             .vece = MO_64
1896         },
1897     };
1899     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
1902 TRANS(vmulwev_h_b, LSX, gvec_vvv, MO_8, do_vmulwev_s)
1903 TRANS(vmulwev_w_h, LSX, gvec_vvv, MO_16, do_vmulwev_s)
1904 TRANS(vmulwev_d_w, LSX, gvec_vvv, MO_32, do_vmulwev_s)
1906 static void tcg_gen_mulus2_i64(TCGv_i64 rl, TCGv_i64 rh,
1907                                TCGv_i64 arg1, TCGv_i64 arg2)
1909     tcg_gen_mulsu2_i64(rl, rh, arg2, arg1);
1912 #define VMUL_Q(NAME, FN, idx1, idx2)                      \
1913 static bool trans_## NAME (DisasContext *ctx, arg_vvv *a) \
1914 {                                                         \
1915     TCGv_i64 rh, rl, arg1, arg2;                          \
1916                                                           \
1917     if (!avail_LSX(ctx)) {                                \
1918         return false;                                     \
1919     }                                                     \
1920                                                           \
1921     rh = tcg_temp_new_i64();                              \
1922     rl = tcg_temp_new_i64();                              \
1923     arg1 = tcg_temp_new_i64();                            \
1924     arg2 = tcg_temp_new_i64();                            \
1925                                                           \
1926     get_vreg64(arg1, a->vj, idx1);                        \
1927     get_vreg64(arg2, a->vk, idx2);                        \
1928                                                           \
1929     tcg_gen_## FN ##_i64(rl, rh, arg1, arg2);             \
1930                                                           \
1931     set_vreg64(rh, a->vd, 1);                             \
1932     set_vreg64(rl, a->vd, 0);                             \
1933                                                           \
1934     return true;                                          \
1937 VMUL_Q(vmulwev_q_d, muls2, 0, 0)
1938 VMUL_Q(vmulwod_q_d, muls2, 1, 1)
1939 VMUL_Q(vmulwev_q_du, mulu2, 0, 0)
1940 VMUL_Q(vmulwod_q_du, mulu2, 1, 1)
1941 VMUL_Q(vmulwev_q_du_d, mulus2, 0, 0)
1942 VMUL_Q(vmulwod_q_du_d, mulus2, 1, 1)
1944 static void gen_vmulwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
1946     TCGv_vec t1, t2;
1947     int halfbits = 4 << vece;
1949     t1 = tcg_temp_new_vec_matching(a);
1950     t2 = tcg_temp_new_vec_matching(b);
1951     tcg_gen_sari_vec(vece, t1, a, halfbits);
1952     tcg_gen_sari_vec(vece, t2, b, halfbits);
1953     tcg_gen_mul_vec(vece, t, t1, t2);
1956 static void gen_vmulwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
1958     TCGv_i32 t1, t2;
1960     t1 = tcg_temp_new_i32();
1961     t2 = tcg_temp_new_i32();
1962     tcg_gen_sari_i32(t1, a, 16);
1963     tcg_gen_sari_i32(t2, b, 16);
1964     tcg_gen_mul_i32(t, t1, t2);
1967 static void gen_vmulwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
1969     TCGv_i64 t1, t2;
1971     t1 = tcg_temp_new_i64();
1972     t2 = tcg_temp_new_i64();
1973     tcg_gen_sari_i64(t1, a, 32);
1974     tcg_gen_sari_i64(t2, b, 32);
1975     tcg_gen_mul_i64(t, t1, t2);
1978 static void do_vmulwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
1979                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
1981     static const TCGOpcode vecop_list[] = {
1982         INDEX_op_sari_vec, INDEX_op_mul_vec, 0
1983         };
1984     static const GVecGen3 op[3] = {
1985         {
1986             .fniv = gen_vmulwod_s,
1987             .fno = gen_helper_vmulwod_h_b,
1988             .opt_opc = vecop_list,
1989             .vece = MO_16
1990         },
1991         {
1992             .fni4 = gen_vmulwod_w_h,
1993             .fniv = gen_vmulwod_s,
1994             .fno = gen_helper_vmulwod_w_h,
1995             .opt_opc = vecop_list,
1996             .vece = MO_32
1997         },
1998         {
1999             .fni8 = gen_vmulwod_d_w,
2000             .fniv = gen_vmulwod_s,
2001             .fno = gen_helper_vmulwod_d_w,
2002             .opt_opc = vecop_list,
2003             .vece = MO_64
2004         },
2005     };
2007     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2010 TRANS(vmulwod_h_b, LSX, gvec_vvv, MO_8, do_vmulwod_s)
2011 TRANS(vmulwod_w_h, LSX, gvec_vvv, MO_16, do_vmulwod_s)
2012 TRANS(vmulwod_d_w, LSX, gvec_vvv, MO_32, do_vmulwod_s)
2014 static void gen_vmulwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2016     TCGv_vec t1, t2, mask;
2018     t1 = tcg_temp_new_vec_matching(a);
2019     t2 = tcg_temp_new_vec_matching(b);
2020     mask = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
2021     tcg_gen_and_vec(vece, t1, a, mask);
2022     tcg_gen_and_vec(vece, t2, b, mask);
2023     tcg_gen_mul_vec(vece, t, t1, t2);
2026 static void gen_vmulwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2028     TCGv_i32 t1, t2;
2030     t1 = tcg_temp_new_i32();
2031     t2 = tcg_temp_new_i32();
2032     tcg_gen_ext16u_i32(t1, a);
2033     tcg_gen_ext16u_i32(t2, b);
2034     tcg_gen_mul_i32(t, t1, t2);
2037 static void gen_vmulwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2039     TCGv_i64 t1, t2;
2041     t1 = tcg_temp_new_i64();
2042     t2 = tcg_temp_new_i64();
2043     tcg_gen_ext32u_i64(t1, a);
2044     tcg_gen_ext32u_i64(t2, b);
2045     tcg_gen_mul_i64(t, t1, t2);
2048 static void do_vmulwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2049                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2051     static const TCGOpcode vecop_list[] = {
2052         INDEX_op_mul_vec, 0
2053         };
2054     static const GVecGen3 op[3] = {
2055         {
2056             .fniv = gen_vmulwev_u,
2057             .fno = gen_helper_vmulwev_h_bu,
2058             .opt_opc = vecop_list,
2059             .vece = MO_16
2060         },
2061         {
2062             .fni4 = gen_vmulwev_w_hu,
2063             .fniv = gen_vmulwev_u,
2064             .fno = gen_helper_vmulwev_w_hu,
2065             .opt_opc = vecop_list,
2066             .vece = MO_32
2067         },
2068         {
2069             .fni8 = gen_vmulwev_d_wu,
2070             .fniv = gen_vmulwev_u,
2071             .fno = gen_helper_vmulwev_d_wu,
2072             .opt_opc = vecop_list,
2073             .vece = MO_64
2074         },
2075     };
2077     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2080 TRANS(vmulwev_h_bu, LSX, gvec_vvv, MO_8, do_vmulwev_u)
2081 TRANS(vmulwev_w_hu, LSX, gvec_vvv, MO_16, do_vmulwev_u)
2082 TRANS(vmulwev_d_wu, LSX, gvec_vvv, MO_32, do_vmulwev_u)
2084 static void gen_vmulwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2086     TCGv_vec t1, t2;
2087     int halfbits = 4 << vece;
2089     t1 = tcg_temp_new_vec_matching(a);
2090     t2 = tcg_temp_new_vec_matching(b);
2091     tcg_gen_shri_vec(vece, t1, a, halfbits);
2092     tcg_gen_shri_vec(vece, t2, b, halfbits);
2093     tcg_gen_mul_vec(vece, t, t1, t2);
2096 static void gen_vmulwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2098     TCGv_i32 t1, t2;
2100     t1 = tcg_temp_new_i32();
2101     t2 = tcg_temp_new_i32();
2102     tcg_gen_shri_i32(t1, a, 16);
2103     tcg_gen_shri_i32(t2, b, 16);
2104     tcg_gen_mul_i32(t, t1, t2);
2107 static void gen_vmulwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2109     TCGv_i64 t1, t2;
2111     t1 = tcg_temp_new_i64();
2112     t2 = tcg_temp_new_i64();
2113     tcg_gen_shri_i64(t1, a, 32);
2114     tcg_gen_shri_i64(t2, b, 32);
2115     tcg_gen_mul_i64(t, t1, t2);
2118 static void do_vmulwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2119                          uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2121     static const TCGOpcode vecop_list[] = {
2122         INDEX_op_shri_vec, INDEX_op_mul_vec, 0
2123         };
2124     static const GVecGen3 op[3] = {
2125         {
2126             .fniv = gen_vmulwod_u,
2127             .fno = gen_helper_vmulwod_h_bu,
2128             .opt_opc = vecop_list,
2129             .vece = MO_16
2130         },
2131         {
2132             .fni4 = gen_vmulwod_w_hu,
2133             .fniv = gen_vmulwod_u,
2134             .fno = gen_helper_vmulwod_w_hu,
2135             .opt_opc = vecop_list,
2136             .vece = MO_32
2137         },
2138         {
2139             .fni8 = gen_vmulwod_d_wu,
2140             .fniv = gen_vmulwod_u,
2141             .fno = gen_helper_vmulwod_d_wu,
2142             .opt_opc = vecop_list,
2143             .vece = MO_64
2144         },
2145     };
2147     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2150 TRANS(vmulwod_h_bu, LSX, gvec_vvv, MO_8, do_vmulwod_u)
2151 TRANS(vmulwod_w_hu, LSX, gvec_vvv, MO_16, do_vmulwod_u)
2152 TRANS(vmulwod_d_wu, LSX, gvec_vvv, MO_32, do_vmulwod_u)
2154 static void gen_vmulwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2156     TCGv_vec t1, t2, mask;
2157     int halfbits = 4 << vece;
2159     t1 = tcg_temp_new_vec_matching(a);
2160     t2 = tcg_temp_new_vec_matching(b);
2161     mask = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
2162     tcg_gen_and_vec(vece, t1, a, mask);
2163     tcg_gen_shli_vec(vece, t2, b, halfbits);
2164     tcg_gen_sari_vec(vece, t2, t2, halfbits);
2165     tcg_gen_mul_vec(vece, t, t1, t2);
2168 static void gen_vmulwev_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2170     TCGv_i32 t1, t2;
2172     t1 = tcg_temp_new_i32();
2173     t2 = tcg_temp_new_i32();
2174     tcg_gen_ext16u_i32(t1, a);
2175     tcg_gen_ext16s_i32(t2, b);
2176     tcg_gen_mul_i32(t, t1, t2);
2179 static void gen_vmulwev_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2181     TCGv_i64 t1, t2;
2183     t1 = tcg_temp_new_i64();
2184     t2 = tcg_temp_new_i64();
2185     tcg_gen_ext32u_i64(t1, a);
2186     tcg_gen_ext32s_i64(t2, b);
2187     tcg_gen_mul_i64(t, t1, t2);
2190 static void do_vmulwev_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2191                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2193     static const TCGOpcode vecop_list[] = {
2194         INDEX_op_shli_vec, INDEX_op_sari_vec, INDEX_op_mul_vec, 0
2195         };
2196     static const GVecGen3 op[3] = {
2197         {
2198             .fniv = gen_vmulwev_u_s,
2199             .fno = gen_helper_vmulwev_h_bu_b,
2200             .opt_opc = vecop_list,
2201             .vece = MO_16
2202         },
2203         {
2204             .fni4 = gen_vmulwev_w_hu_h,
2205             .fniv = gen_vmulwev_u_s,
2206             .fno = gen_helper_vmulwev_w_hu_h,
2207             .opt_opc = vecop_list,
2208             .vece = MO_32
2209         },
2210         {
2211             .fni8 = gen_vmulwev_d_wu_w,
2212             .fniv = gen_vmulwev_u_s,
2213             .fno = gen_helper_vmulwev_d_wu_w,
2214             .opt_opc = vecop_list,
2215             .vece = MO_64
2216         },
2217     };
2219     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2222 TRANS(vmulwev_h_bu_b, LSX, gvec_vvv, MO_8, do_vmulwev_u_s)
2223 TRANS(vmulwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vmulwev_u_s)
2224 TRANS(vmulwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vmulwev_u_s)
2226 static void gen_vmulwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2228     TCGv_vec t1, t2;
2229     int halfbits = 4 << vece;
2231     t1 = tcg_temp_new_vec_matching(a);
2232     t2 = tcg_temp_new_vec_matching(b);
2233     tcg_gen_shri_vec(vece, t1, a, halfbits);
2234     tcg_gen_sari_vec(vece, t2, b, halfbits);
2235     tcg_gen_mul_vec(vece, t, t1, t2);
2238 static void gen_vmulwod_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2240     TCGv_i32 t1, t2;
2242     t1 = tcg_temp_new_i32();
2243     t2 = tcg_temp_new_i32();
2244     tcg_gen_shri_i32(t1, a, 16);
2245     tcg_gen_sari_i32(t2, b, 16);
2246     tcg_gen_mul_i32(t, t1, t2);
2248 static void gen_vmulwod_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2250     TCGv_i64 t1, t2;
2252     t1 = tcg_temp_new_i64();
2253     t2 = tcg_temp_new_i64();
2254     tcg_gen_shri_i64(t1, a, 32);
2255     tcg_gen_sari_i64(t2, b, 32);
2256     tcg_gen_mul_i64(t, t1, t2);
2259 static void do_vmulwod_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2260                            uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2262     static const TCGOpcode vecop_list[] = {
2263         INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_mul_vec, 0
2264         };
2265     static const GVecGen3 op[3] = {
2266         {
2267             .fniv = gen_vmulwod_u_s,
2268             .fno = gen_helper_vmulwod_h_bu_b,
2269             .opt_opc = vecop_list,
2270             .vece = MO_16
2271         },
2272         {
2273             .fni4 = gen_vmulwod_w_hu_h,
2274             .fniv = gen_vmulwod_u_s,
2275             .fno = gen_helper_vmulwod_w_hu_h,
2276             .opt_opc = vecop_list,
2277             .vece = MO_32
2278         },
2279         {
2280             .fni8 = gen_vmulwod_d_wu_w,
2281             .fniv = gen_vmulwod_u_s,
2282             .fno = gen_helper_vmulwod_d_wu_w,
2283             .opt_opc = vecop_list,
2284             .vece = MO_64
2285         },
2286     };
2288     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2291 TRANS(vmulwod_h_bu_b, LSX, gvec_vvv, MO_8, do_vmulwod_u_s)
2292 TRANS(vmulwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vmulwod_u_s)
2293 TRANS(vmulwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vmulwod_u_s)
2295 static void gen_vmadd(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2297     TCGv_vec t1;
2299     t1 = tcg_temp_new_vec_matching(t);
2300     tcg_gen_mul_vec(vece, t1, a, b);
2301     tcg_gen_add_vec(vece, t, t, t1);
2304 static void gen_vmadd_w(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2306     TCGv_i32 t1;
2308     t1 = tcg_temp_new_i32();
2309     tcg_gen_mul_i32(t1, a, b);
2310     tcg_gen_add_i32(t, t, t1);
2313 static void gen_vmadd_d(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2315     TCGv_i64 t1;
2317     t1 = tcg_temp_new_i64();
2318     tcg_gen_mul_i64(t1, a, b);
2319     tcg_gen_add_i64(t, t, t1);
2322 static void do_vmadd(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2323                      uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2325     static const TCGOpcode vecop_list[] = {
2326         INDEX_op_mul_vec, INDEX_op_add_vec, 0
2327         };
2328     static const GVecGen3 op[4] = {
2329         {
2330             .fniv = gen_vmadd,
2331             .fno = gen_helper_vmadd_b,
2332             .load_dest = true,
2333             .opt_opc = vecop_list,
2334             .vece = MO_8
2335         },
2336         {
2337             .fniv = gen_vmadd,
2338             .fno = gen_helper_vmadd_h,
2339             .load_dest = true,
2340             .opt_opc = vecop_list,
2341             .vece = MO_16
2342         },
2343         {
2344             .fni4 = gen_vmadd_w,
2345             .fniv = gen_vmadd,
2346             .fno = gen_helper_vmadd_w,
2347             .load_dest = true,
2348             .opt_opc = vecop_list,
2349             .vece = MO_32
2350         },
2351         {
2352             .fni8 = gen_vmadd_d,
2353             .fniv = gen_vmadd,
2354             .fno = gen_helper_vmadd_d,
2355             .load_dest = true,
2356             .opt_opc = vecop_list,
2357             .vece = MO_64
2358         },
2359     };
2361     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2364 TRANS(vmadd_b, LSX, gvec_vvv, MO_8, do_vmadd)
2365 TRANS(vmadd_h, LSX, gvec_vvv, MO_16, do_vmadd)
2366 TRANS(vmadd_w, LSX, gvec_vvv, MO_32, do_vmadd)
2367 TRANS(vmadd_d, LSX, gvec_vvv, MO_64, do_vmadd)
2369 static void gen_vmsub(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2371     TCGv_vec t1;
2373     t1 = tcg_temp_new_vec_matching(t);
2374     tcg_gen_mul_vec(vece, t1, a, b);
2375     tcg_gen_sub_vec(vece, t, t, t1);
2378 static void gen_vmsub_w(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2380     TCGv_i32 t1;
2382     t1 = tcg_temp_new_i32();
2383     tcg_gen_mul_i32(t1, a, b);
2384     tcg_gen_sub_i32(t, t, t1);
2387 static void gen_vmsub_d(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2389     TCGv_i64 t1;
2391     t1 = tcg_temp_new_i64();
2392     tcg_gen_mul_i64(t1, a, b);
2393     tcg_gen_sub_i64(t, t, t1);
2396 static void do_vmsub(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2397                      uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2399     static const TCGOpcode vecop_list[] = {
2400         INDEX_op_mul_vec, INDEX_op_sub_vec, 0
2401         };
2402     static const GVecGen3 op[4] = {
2403         {
2404             .fniv = gen_vmsub,
2405             .fno = gen_helper_vmsub_b,
2406             .load_dest = true,
2407             .opt_opc = vecop_list,
2408             .vece = MO_8
2409         },
2410         {
2411             .fniv = gen_vmsub,
2412             .fno = gen_helper_vmsub_h,
2413             .load_dest = true,
2414             .opt_opc = vecop_list,
2415             .vece = MO_16
2416         },
2417         {
2418             .fni4 = gen_vmsub_w,
2419             .fniv = gen_vmsub,
2420             .fno = gen_helper_vmsub_w,
2421             .load_dest = true,
2422             .opt_opc = vecop_list,
2423             .vece = MO_32
2424         },
2425         {
2426             .fni8 = gen_vmsub_d,
2427             .fniv = gen_vmsub,
2428             .fno = gen_helper_vmsub_d,
2429             .load_dest = true,
2430             .opt_opc = vecop_list,
2431             .vece = MO_64
2432         },
2433     };
2435     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2438 TRANS(vmsub_b, LSX, gvec_vvv, MO_8, do_vmsub)
2439 TRANS(vmsub_h, LSX, gvec_vvv, MO_16, do_vmsub)
2440 TRANS(vmsub_w, LSX, gvec_vvv, MO_32, do_vmsub)
2441 TRANS(vmsub_d, LSX, gvec_vvv, MO_64, do_vmsub)
2443 static void gen_vmaddwev_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2445     TCGv_vec t1, t2, t3;
2446     int halfbits = 4 << vece;
2448     t1 = tcg_temp_new_vec_matching(a);
2449     t2 = tcg_temp_new_vec_matching(b);
2450     t3 = tcg_temp_new_vec_matching(t);
2451     tcg_gen_shli_vec(vece, t1, a, halfbits);
2452     tcg_gen_sari_vec(vece, t1, t1, halfbits);
2453     tcg_gen_shli_vec(vece, t2, b, halfbits);
2454     tcg_gen_sari_vec(vece, t2, t2, halfbits);
2455     tcg_gen_mul_vec(vece, t3, t1, t2);
2456     tcg_gen_add_vec(vece, t, t, t3);
2459 static void gen_vmaddwev_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2461     TCGv_i32 t1;
2463     t1 = tcg_temp_new_i32();
2464     gen_vmulwev_w_h(t1, a, b);
2465     tcg_gen_add_i32(t, t, t1);
2468 static void gen_vmaddwev_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2470     TCGv_i64 t1;
2472     t1 = tcg_temp_new_i64();
2473     gen_vmulwev_d_w(t1, a, b);
2474     tcg_gen_add_i64(t, t, t1);
2477 static void do_vmaddwev_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2478                           uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2480     static const TCGOpcode vecop_list[] = {
2481         INDEX_op_shli_vec, INDEX_op_sari_vec,
2482         INDEX_op_mul_vec, INDEX_op_add_vec, 0
2483         };
2484     static const GVecGen3 op[3] = {
2485         {
2486             .fniv = gen_vmaddwev_s,
2487             .fno = gen_helper_vmaddwev_h_b,
2488             .load_dest = true,
2489             .opt_opc = vecop_list,
2490             .vece = MO_16
2491         },
2492         {
2493             .fni4 = gen_vmaddwev_w_h,
2494             .fniv = gen_vmaddwev_s,
2495             .fno = gen_helper_vmaddwev_w_h,
2496             .load_dest = true,
2497             .opt_opc = vecop_list,
2498             .vece = MO_32
2499         },
2500         {
2501             .fni8 = gen_vmaddwev_d_w,
2502             .fniv = gen_vmaddwev_s,
2503             .fno = gen_helper_vmaddwev_d_w,
2504             .load_dest = true,
2505             .opt_opc = vecop_list,
2506             .vece = MO_64
2507         },
2508     };
2510     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2513 TRANS(vmaddwev_h_b, LSX, gvec_vvv, MO_8, do_vmaddwev_s)
2514 TRANS(vmaddwev_w_h, LSX, gvec_vvv, MO_16, do_vmaddwev_s)
2515 TRANS(vmaddwev_d_w, LSX, gvec_vvv, MO_32, do_vmaddwev_s)
2517 #define VMADD_Q(NAME, FN, idx1, idx2)                     \
2518 static bool trans_## NAME (DisasContext *ctx, arg_vvv *a) \
2519 {                                                         \
2520     TCGv_i64 rh, rl, arg1, arg2, th, tl;                  \
2521                                                           \
2522     if (!avail_LSX(ctx)) {                                \
2523         return false;                                     \
2524     }                                                     \
2525                                                           \
2526     rh = tcg_temp_new_i64();                              \
2527     rl = tcg_temp_new_i64();                              \
2528     arg1 = tcg_temp_new_i64();                            \
2529     arg2 = tcg_temp_new_i64();                            \
2530     th = tcg_temp_new_i64();                              \
2531     tl = tcg_temp_new_i64();                              \
2532                                                           \
2533     get_vreg64(arg1, a->vj, idx1);                        \
2534     get_vreg64(arg2, a->vk, idx2);                        \
2535     get_vreg64(rh, a->vd, 1);                             \
2536     get_vreg64(rl, a->vd, 0);                             \
2537                                                           \
2538     tcg_gen_## FN ##_i64(tl, th, arg1, arg2);             \
2539     tcg_gen_add2_i64(rl, rh, rl, rh, tl, th);             \
2540                                                           \
2541     set_vreg64(rh, a->vd, 1);                             \
2542     set_vreg64(rl, a->vd, 0);                             \
2543                                                           \
2544     return true;                                          \
2547 VMADD_Q(vmaddwev_q_d, muls2, 0, 0)
2548 VMADD_Q(vmaddwod_q_d, muls2, 1, 1)
2549 VMADD_Q(vmaddwev_q_du, mulu2, 0, 0)
2550 VMADD_Q(vmaddwod_q_du, mulu2, 1, 1)
2551 VMADD_Q(vmaddwev_q_du_d, mulus2, 0, 0)
2552 VMADD_Q(vmaddwod_q_du_d, mulus2, 1, 1)
2554 static void gen_vmaddwod_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2556     TCGv_vec t1, t2, t3;
2557     int halfbits = 4 << vece;
2559     t1 = tcg_temp_new_vec_matching(a);
2560     t2 = tcg_temp_new_vec_matching(b);
2561     t3 = tcg_temp_new_vec_matching(t);
2562     tcg_gen_sari_vec(vece, t1, a, halfbits);
2563     tcg_gen_sari_vec(vece, t2, b, halfbits);
2564     tcg_gen_mul_vec(vece, t3, t1, t2);
2565     tcg_gen_add_vec(vece, t, t, t3);
2568 static void gen_vmaddwod_w_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2570     TCGv_i32 t1;
2572     t1 = tcg_temp_new_i32();
2573     gen_vmulwod_w_h(t1, a, b);
2574     tcg_gen_add_i32(t, t, t1);
2577 static void gen_vmaddwod_d_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2579     TCGv_i64 t1;
2581     t1 = tcg_temp_new_i64();
2582     gen_vmulwod_d_w(t1, a, b);
2583     tcg_gen_add_i64(t, t, t1);
2586 static void do_vmaddwod_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2587                           uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2589     static const TCGOpcode vecop_list[] = {
2590         INDEX_op_sari_vec, INDEX_op_mul_vec, INDEX_op_add_vec, 0
2591         };
2592     static const GVecGen3 op[3] = {
2593         {
2594             .fniv = gen_vmaddwod_s,
2595             .fno = gen_helper_vmaddwod_h_b,
2596             .load_dest = true,
2597             .opt_opc = vecop_list,
2598             .vece = MO_16
2599         },
2600         {
2601             .fni4 = gen_vmaddwod_w_h,
2602             .fniv = gen_vmaddwod_s,
2603             .fno = gen_helper_vmaddwod_w_h,
2604             .load_dest = true,
2605             .opt_opc = vecop_list,
2606             .vece = MO_32
2607         },
2608         {
2609             .fni8 = gen_vmaddwod_d_w,
2610             .fniv = gen_vmaddwod_s,
2611             .fno = gen_helper_vmaddwod_d_w,
2612             .load_dest = true,
2613             .opt_opc = vecop_list,
2614             .vece = MO_64
2615         },
2616     };
2618     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2621 TRANS(vmaddwod_h_b, LSX, gvec_vvv, MO_8, do_vmaddwod_s)
2622 TRANS(vmaddwod_w_h, LSX, gvec_vvv, MO_16, do_vmaddwod_s)
2623 TRANS(vmaddwod_d_w, LSX, gvec_vvv, MO_32, do_vmaddwod_s)
2625 static void gen_vmaddwev_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2627     TCGv_vec t1, t2, mask;
2629     t1 = tcg_temp_new_vec_matching(t);
2630     t2 = tcg_temp_new_vec_matching(b);
2631     mask = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
2632     tcg_gen_and_vec(vece, t1, a, mask);
2633     tcg_gen_and_vec(vece, t2, b, mask);
2634     tcg_gen_mul_vec(vece, t1, t1, t2);
2635     tcg_gen_add_vec(vece, t, t, t1);
2638 static void gen_vmaddwev_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2640     TCGv_i32 t1;
2642     t1 = tcg_temp_new_i32();
2643     gen_vmulwev_w_hu(t1, a, b);
2644     tcg_gen_add_i32(t, t, t1);
2647 static void gen_vmaddwev_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2649     TCGv_i64 t1;
2651     t1 = tcg_temp_new_i64();
2652     gen_vmulwev_d_wu(t1, a, b);
2653     tcg_gen_add_i64(t, t, t1);
2656 static void do_vmaddwev_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2657                           uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2659     static const TCGOpcode vecop_list[] = {
2660         INDEX_op_mul_vec, INDEX_op_add_vec, 0
2661         };
2662     static const GVecGen3 op[3] = {
2663         {
2664             .fniv = gen_vmaddwev_u,
2665             .fno = gen_helper_vmaddwev_h_bu,
2666             .load_dest = true,
2667             .opt_opc = vecop_list,
2668             .vece = MO_16
2669         },
2670         {
2671             .fni4 = gen_vmaddwev_w_hu,
2672             .fniv = gen_vmaddwev_u,
2673             .fno = gen_helper_vmaddwev_w_hu,
2674             .load_dest = true,
2675             .opt_opc = vecop_list,
2676             .vece = MO_32
2677         },
2678         {
2679             .fni8 = gen_vmaddwev_d_wu,
2680             .fniv = gen_vmaddwev_u,
2681             .fno = gen_helper_vmaddwev_d_wu,
2682             .load_dest = true,
2683             .opt_opc = vecop_list,
2684             .vece = MO_64
2685         },
2686     };
2688     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2691 TRANS(vmaddwev_h_bu, LSX, gvec_vvv, MO_8, do_vmaddwev_u)
2692 TRANS(vmaddwev_w_hu, LSX, gvec_vvv, MO_16, do_vmaddwev_u)
2693 TRANS(vmaddwev_d_wu, LSX, gvec_vvv, MO_32, do_vmaddwev_u)
2695 static void gen_vmaddwod_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2697     TCGv_vec t1, t2, t3;
2698     int halfbits = 4 << vece;
2700     t1 = tcg_temp_new_vec_matching(a);
2701     t2 = tcg_temp_new_vec_matching(b);
2702     t3 = tcg_temp_new_vec_matching(t);
2703     tcg_gen_shri_vec(vece, t1, a, halfbits);
2704     tcg_gen_shri_vec(vece, t2, b, halfbits);
2705     tcg_gen_mul_vec(vece, t3, t1, t2);
2706     tcg_gen_add_vec(vece, t, t, t3);
2709 static void gen_vmaddwod_w_hu(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2711     TCGv_i32 t1;
2713     t1 = tcg_temp_new_i32();
2714     gen_vmulwod_w_hu(t1, a, b);
2715     tcg_gen_add_i32(t, t, t1);
2718 static void gen_vmaddwod_d_wu(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2720     TCGv_i64 t1;
2722     t1 = tcg_temp_new_i64();
2723     gen_vmulwod_d_wu(t1, a, b);
2724     tcg_gen_add_i64(t, t, t1);
2727 static void do_vmaddwod_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2728                           uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2730     static const TCGOpcode vecop_list[] = {
2731         INDEX_op_shri_vec, INDEX_op_mul_vec, INDEX_op_add_vec, 0
2732         };
2733     static const GVecGen3 op[3] = {
2734         {
2735             .fniv = gen_vmaddwod_u,
2736             .fno = gen_helper_vmaddwod_h_bu,
2737             .load_dest = true,
2738             .opt_opc = vecop_list,
2739             .vece = MO_16
2740         },
2741         {
2742             .fni4 = gen_vmaddwod_w_hu,
2743             .fniv = gen_vmaddwod_u,
2744             .fno = gen_helper_vmaddwod_w_hu,
2745             .load_dest = true,
2746             .opt_opc = vecop_list,
2747             .vece = MO_32
2748         },
2749         {
2750             .fni8 = gen_vmaddwod_d_wu,
2751             .fniv = gen_vmaddwod_u,
2752             .fno = gen_helper_vmaddwod_d_wu,
2753             .load_dest = true,
2754             .opt_opc = vecop_list,
2755             .vece = MO_64
2756         },
2757     };
2759     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2762 TRANS(vmaddwod_h_bu, LSX, gvec_vvv, MO_8, do_vmaddwod_u)
2763 TRANS(vmaddwod_w_hu, LSX, gvec_vvv, MO_16, do_vmaddwod_u)
2764 TRANS(vmaddwod_d_wu, LSX, gvec_vvv, MO_32, do_vmaddwod_u)
2766 static void gen_vmaddwev_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2768     TCGv_vec t1, t2, mask;
2769     int halfbits = 4 << vece;
2771     t1 = tcg_temp_new_vec_matching(a);
2772     t2 = tcg_temp_new_vec_matching(b);
2773     mask = tcg_constant_vec_matching(t, vece, MAKE_64BIT_MASK(0, 4 << vece));
2774     tcg_gen_and_vec(vece, t1, a, mask);
2775     tcg_gen_shli_vec(vece, t2, b, halfbits);
2776     tcg_gen_sari_vec(vece, t2, t2, halfbits);
2777     tcg_gen_mul_vec(vece, t1, t1, t2);
2778     tcg_gen_add_vec(vece, t, t, t1);
2781 static void gen_vmaddwev_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2783     TCGv_i32 t1;
2785     t1 = tcg_temp_new_i32();
2786     gen_vmulwev_w_hu_h(t1, a, b);
2787     tcg_gen_add_i32(t, t, t1);
2790 static void gen_vmaddwev_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2792     TCGv_i64 t1;
2794     t1 = tcg_temp_new_i64();
2795     gen_vmulwev_d_wu_w(t1, a, b);
2796     tcg_gen_add_i64(t, t, t1);
2799 static void do_vmaddwev_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2800                             uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2802     static const TCGOpcode vecop_list[] = {
2803         INDEX_op_shli_vec, INDEX_op_sari_vec,
2804         INDEX_op_mul_vec, INDEX_op_add_vec, 0
2805         };
2806     static const GVecGen3 op[3] = {
2807         {
2808             .fniv = gen_vmaddwev_u_s,
2809             .fno = gen_helper_vmaddwev_h_bu_b,
2810             .load_dest = true,
2811             .opt_opc = vecop_list,
2812             .vece = MO_16
2813         },
2814         {
2815             .fni4 = gen_vmaddwev_w_hu_h,
2816             .fniv = gen_vmaddwev_u_s,
2817             .fno = gen_helper_vmaddwev_w_hu_h,
2818             .load_dest = true,
2819             .opt_opc = vecop_list,
2820             .vece = MO_32
2821         },
2822         {
2823             .fni8 = gen_vmaddwev_d_wu_w,
2824             .fniv = gen_vmaddwev_u_s,
2825             .fno = gen_helper_vmaddwev_d_wu_w,
2826             .load_dest = true,
2827             .opt_opc = vecop_list,
2828             .vece = MO_64
2829         },
2830     };
2832     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2835 TRANS(vmaddwev_h_bu_b, LSX, gvec_vvv, MO_8, do_vmaddwev_u_s)
2836 TRANS(vmaddwev_w_hu_h, LSX, gvec_vvv, MO_16, do_vmaddwev_u_s)
2837 TRANS(vmaddwev_d_wu_w, LSX, gvec_vvv, MO_32, do_vmaddwev_u_s)
2839 static void gen_vmaddwod_u_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
2841     TCGv_vec t1, t2, t3;
2842     int halfbits = 4 << vece;
2844     t1 = tcg_temp_new_vec_matching(a);
2845     t2 = tcg_temp_new_vec_matching(b);
2846     t3 = tcg_temp_new_vec_matching(t);
2847     tcg_gen_shri_vec(vece, t1, a, halfbits);
2848     tcg_gen_sari_vec(vece, t2, b, halfbits);
2849     tcg_gen_mul_vec(vece, t3, t1, t2);
2850     tcg_gen_add_vec(vece, t, t, t3);
2853 static void gen_vmaddwod_w_hu_h(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
2855     TCGv_i32 t1;
2857     t1 = tcg_temp_new_i32();
2858     gen_vmulwod_w_hu_h(t1, a, b);
2859     tcg_gen_add_i32(t, t, t1);
2862 static void gen_vmaddwod_d_wu_w(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
2864     TCGv_i64 t1;
2866     t1 = tcg_temp_new_i64();
2867     gen_vmulwod_d_wu_w(t1, a, b);
2868     tcg_gen_add_i64(t, t, t1);
2871 static void do_vmaddwod_u_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2872                             uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
2874     static const TCGOpcode vecop_list[] = {
2875         INDEX_op_shri_vec, INDEX_op_sari_vec,
2876         INDEX_op_mul_vec, INDEX_op_add_vec, 0
2877         };
2878     static const GVecGen3 op[3] = {
2879         {
2880             .fniv = gen_vmaddwod_u_s,
2881             .fno = gen_helper_vmaddwod_h_bu_b,
2882             .load_dest = true,
2883             .opt_opc = vecop_list,
2884             .vece = MO_16
2885         },
2886         {
2887             .fni4 = gen_vmaddwod_w_hu_h,
2888             .fniv = gen_vmaddwod_u_s,
2889             .fno = gen_helper_vmaddwod_w_hu_h,
2890             .load_dest = true,
2891             .opt_opc = vecop_list,
2892             .vece = MO_32
2893         },
2894         {
2895             .fni8 = gen_vmaddwod_d_wu_w,
2896             .fniv = gen_vmaddwod_u_s,
2897             .fno = gen_helper_vmaddwod_d_wu_w,
2898             .load_dest = true,
2899             .opt_opc = vecop_list,
2900             .vece = MO_64
2901         },
2902     };
2904     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
2907 TRANS(vmaddwod_h_bu_b, LSX, gvec_vvv, MO_8, do_vmaddwod_u_s)
2908 TRANS(vmaddwod_w_hu_h, LSX, gvec_vvv, MO_16, do_vmaddwod_u_s)
2909 TRANS(vmaddwod_d_wu_w, LSX, gvec_vvv, MO_32, do_vmaddwod_u_s)
2911 TRANS(vdiv_b, LSX, gen_vvv, gen_helper_vdiv_b)
2912 TRANS(vdiv_h, LSX, gen_vvv, gen_helper_vdiv_h)
2913 TRANS(vdiv_w, LSX, gen_vvv, gen_helper_vdiv_w)
2914 TRANS(vdiv_d, LSX, gen_vvv, gen_helper_vdiv_d)
2915 TRANS(vdiv_bu, LSX, gen_vvv, gen_helper_vdiv_bu)
2916 TRANS(vdiv_hu, LSX, gen_vvv, gen_helper_vdiv_hu)
2917 TRANS(vdiv_wu, LSX, gen_vvv, gen_helper_vdiv_wu)
2918 TRANS(vdiv_du, LSX, gen_vvv, gen_helper_vdiv_du)
2919 TRANS(vmod_b, LSX, gen_vvv, gen_helper_vmod_b)
2920 TRANS(vmod_h, LSX, gen_vvv, gen_helper_vmod_h)
2921 TRANS(vmod_w, LSX, gen_vvv, gen_helper_vmod_w)
2922 TRANS(vmod_d, LSX, gen_vvv, gen_helper_vmod_d)
2923 TRANS(vmod_bu, LSX, gen_vvv, gen_helper_vmod_bu)
2924 TRANS(vmod_hu, LSX, gen_vvv, gen_helper_vmod_hu)
2925 TRANS(vmod_wu, LSX, gen_vvv, gen_helper_vmod_wu)
2926 TRANS(vmod_du, LSX, gen_vvv, gen_helper_vmod_du)
2928 static void gen_vsat_s(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
2930     TCGv_vec min;
2932     min = tcg_temp_new_vec_matching(t);
2933     tcg_gen_not_vec(vece, min, max);
2934     tcg_gen_smax_vec(vece, t, a, min);
2935     tcg_gen_smin_vec(vece, t, t, max);
2938 static void do_vsat_s(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2939                       int64_t imm, uint32_t oprsz, uint32_t maxsz)
2941     static const TCGOpcode vecop_list[] = {
2942         INDEX_op_smax_vec, INDEX_op_smin_vec, 0
2943         };
2944     static const GVecGen2s op[4] = {
2945         {
2946             .fniv = gen_vsat_s,
2947             .fno = gen_helper_vsat_b,
2948             .opt_opc = vecop_list,
2949             .vece = MO_8
2950         },
2951         {
2952             .fniv = gen_vsat_s,
2953             .fno = gen_helper_vsat_h,
2954             .opt_opc = vecop_list,
2955             .vece = MO_16
2956         },
2957         {
2958             .fniv = gen_vsat_s,
2959             .fno = gen_helper_vsat_w,
2960             .opt_opc = vecop_list,
2961             .vece = MO_32
2962         },
2963         {
2964             .fniv = gen_vsat_s,
2965             .fno = gen_helper_vsat_d,
2966             .opt_opc = vecop_list,
2967             .vece = MO_64
2968         },
2969     };
2971     tcg_gen_gvec_2s(vd_ofs, vj_ofs, oprsz, maxsz,
2972                     tcg_constant_i64((1ll<< imm) -1), &op[vece]);
2975 TRANS(vsat_b, LSX, gvec_vv_i, MO_8, do_vsat_s)
2976 TRANS(vsat_h, LSX, gvec_vv_i, MO_16, do_vsat_s)
2977 TRANS(vsat_w, LSX, gvec_vv_i, MO_32, do_vsat_s)
2978 TRANS(vsat_d, LSX, gvec_vv_i, MO_64, do_vsat_s)
2980 static void gen_vsat_u(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec max)
2982     tcg_gen_umin_vec(vece, t, a, max);
2985 static void do_vsat_u(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
2986                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
2988     uint64_t max;
2989     static const TCGOpcode vecop_list[] = {
2990         INDEX_op_umin_vec, 0
2991         };
2992     static const GVecGen2s op[4] = {
2993         {
2994             .fniv = gen_vsat_u,
2995             .fno = gen_helper_vsat_bu,
2996             .opt_opc = vecop_list,
2997             .vece = MO_8
2998         },
2999         {
3000             .fniv = gen_vsat_u,
3001             .fno = gen_helper_vsat_hu,
3002             .opt_opc = vecop_list,
3003             .vece = MO_16
3004         },
3005         {
3006             .fniv = gen_vsat_u,
3007             .fno = gen_helper_vsat_wu,
3008             .opt_opc = vecop_list,
3009             .vece = MO_32
3010         },
3011         {
3012             .fniv = gen_vsat_u,
3013             .fno = gen_helper_vsat_du,
3014             .opt_opc = vecop_list,
3015             .vece = MO_64
3016         },
3017     };
3019     max = (imm == 0x3f) ? UINT64_MAX : (1ull << (imm + 1)) - 1;
3020     tcg_gen_gvec_2s(vd_ofs, vj_ofs, oprsz, maxsz,
3021                     tcg_constant_i64(max), &op[vece]);
3024 TRANS(vsat_bu, LSX, gvec_vv_i, MO_8, do_vsat_u)
3025 TRANS(vsat_hu, LSX, gvec_vv_i, MO_16, do_vsat_u)
3026 TRANS(vsat_wu, LSX, gvec_vv_i, MO_32, do_vsat_u)
3027 TRANS(vsat_du, LSX, gvec_vv_i, MO_64, do_vsat_u)
3029 TRANS(vexth_h_b, LSX, gen_vv, gen_helper_vexth_h_b)
3030 TRANS(vexth_w_h, LSX, gen_vv, gen_helper_vexth_w_h)
3031 TRANS(vexth_d_w, LSX, gen_vv, gen_helper_vexth_d_w)
3032 TRANS(vexth_q_d, LSX, gen_vv, gen_helper_vexth_q_d)
3033 TRANS(vexth_hu_bu, LSX, gen_vv, gen_helper_vexth_hu_bu)
3034 TRANS(vexth_wu_hu, LSX, gen_vv, gen_helper_vexth_wu_hu)
3035 TRANS(vexth_du_wu, LSX, gen_vv, gen_helper_vexth_du_wu)
3036 TRANS(vexth_qu_du, LSX, gen_vv, gen_helper_vexth_qu_du)
3038 static void gen_vsigncov(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
3040     TCGv_vec t1, zero;
3042     t1 = tcg_temp_new_vec_matching(t);
3043     zero = tcg_constant_vec_matching(t, vece, 0);
3045     tcg_gen_neg_vec(vece, t1, b);
3046     tcg_gen_cmpsel_vec(TCG_COND_LT, vece, t, a, zero, t1, b);
3047     tcg_gen_cmpsel_vec(TCG_COND_EQ, vece, t, a, zero, zero, t);
3050 static void do_vsigncov(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3051                         uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
3053     static const TCGOpcode vecop_list[] = {
3054         INDEX_op_neg_vec, INDEX_op_cmpsel_vec, 0
3055         };
3056     static const GVecGen3 op[4] = {
3057         {
3058             .fniv = gen_vsigncov,
3059             .fno = gen_helper_vsigncov_b,
3060             .opt_opc = vecop_list,
3061             .vece = MO_8
3062         },
3063         {
3064             .fniv = gen_vsigncov,
3065             .fno = gen_helper_vsigncov_h,
3066             .opt_opc = vecop_list,
3067             .vece = MO_16
3068         },
3069         {
3070             .fniv = gen_vsigncov,
3071             .fno = gen_helper_vsigncov_w,
3072             .opt_opc = vecop_list,
3073             .vece = MO_32
3074         },
3075         {
3076             .fniv = gen_vsigncov,
3077             .fno = gen_helper_vsigncov_d,
3078             .opt_opc = vecop_list,
3079             .vece = MO_64
3080         },
3081     };
3083     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
3086 TRANS(vsigncov_b, LSX, gvec_vvv, MO_8, do_vsigncov)
3087 TRANS(vsigncov_h, LSX, gvec_vvv, MO_16, do_vsigncov)
3088 TRANS(vsigncov_w, LSX, gvec_vvv, MO_32, do_vsigncov)
3089 TRANS(vsigncov_d, LSX, gvec_vvv, MO_64, do_vsigncov)
3091 TRANS(vmskltz_b, LSX, gen_vv, gen_helper_vmskltz_b)
3092 TRANS(vmskltz_h, LSX, gen_vv, gen_helper_vmskltz_h)
3093 TRANS(vmskltz_w, LSX, gen_vv, gen_helper_vmskltz_w)
3094 TRANS(vmskltz_d, LSX, gen_vv, gen_helper_vmskltz_d)
3095 TRANS(vmskgez_b, LSX, gen_vv, gen_helper_vmskgez_b)
3096 TRANS(vmsknz_b, LSX, gen_vv, gen_helper_vmsknz_b)
3098 #define EXPAND_BYTE(bit)  ((uint64_t)(bit ? 0xff : 0))
3100 static uint64_t vldi_get_value(DisasContext *ctx, uint32_t imm)
3102     int mode;
3103     uint64_t data, t;
3105     /*
3106      * imm bit [11:8] is mode, mode value is 0-12.
3107      * other values are invalid.
3108      */
3109     mode = (imm >> 8) & 0xf;
3110     t =  imm & 0xff;
3111     switch (mode) {
3112     case 0:
3113         /* data: {2{24'0, imm[7:0]}} */
3114         data =  (t << 32) | t ;
3115         break;
3116     case 1:
3117         /* data: {2{16'0, imm[7:0], 8'0}} */
3118         data = (t << 24) | (t << 8);
3119         break;
3120     case 2:
3121         /* data: {2{8'0, imm[7:0], 16'0}} */
3122         data = (t << 48) | (t << 16);
3123         break;
3124     case 3:
3125         /* data: {2{imm[7:0], 24'0}} */
3126         data = (t << 56) | (t << 24);
3127         break;
3128     case 4:
3129         /* data: {4{8'0, imm[7:0]}} */
3130         data = (t << 48) | (t << 32) | (t << 16) | t;
3131         break;
3132     case 5:
3133         /* data: {4{imm[7:0], 8'0}} */
3134         data = (t << 56) |(t << 40) | (t << 24) | (t << 8);
3135         break;
3136     case 6:
3137         /* data: {2{16'0, imm[7:0], 8'1}} */
3138         data = (t << 40) | ((uint64_t)0xff << 32) | (t << 8) | 0xff;
3139         break;
3140     case 7:
3141         /* data: {2{8'0, imm[7:0], 16'1}} */
3142         data = (t << 48) | ((uint64_t)0xffff << 32) | (t << 16) | 0xffff;
3143         break;
3144     case 8:
3145         /* data: {8{imm[7:0]}} */
3146         data =(t << 56) | (t << 48) | (t << 40) | (t << 32) |
3147               (t << 24) | (t << 16) | (t << 8) | t;
3148         break;
3149     case 9:
3150         /* data: {{8{imm[7]}, ..., 8{imm[0]}}} */
3151         {
3152             uint64_t b0,b1,b2,b3,b4,b5,b6,b7;
3153             b0 = t& 0x1;
3154             b1 = (t & 0x2) >> 1;
3155             b2 = (t & 0x4) >> 2;
3156             b3 = (t & 0x8) >> 3;
3157             b4 = (t & 0x10) >> 4;
3158             b5 = (t & 0x20) >> 5;
3159             b6 = (t & 0x40) >> 6;
3160             b7 = (t & 0x80) >> 7;
3161             data = (EXPAND_BYTE(b7) << 56) |
3162                    (EXPAND_BYTE(b6) << 48) |
3163                    (EXPAND_BYTE(b5) << 40) |
3164                    (EXPAND_BYTE(b4) << 32) |
3165                    (EXPAND_BYTE(b3) << 24) |
3166                    (EXPAND_BYTE(b2) << 16) |
3167                    (EXPAND_BYTE(b1) <<  8) |
3168                    EXPAND_BYTE(b0);
3169         }
3170         break;
3171     case 10:
3172         /* data: {2{imm[7], ~imm[6], {5{imm[6]}}, imm[5:0], 19'0}} */
3173         {
3174             uint64_t b6, b7;
3175             uint64_t t0, t1;
3176             b6 = (imm & 0x40) >> 6;
3177             b7 = (imm & 0x80) >> 7;
3178             t0 = (imm & 0x3f);
3179             t1 = (b7 << 6) | ((1-b6) << 5) | (uint64_t)(b6 ? 0x1f : 0);
3180             data  = (t1 << 57) | (t0 << 51) | (t1 << 25) | (t0 << 19);
3181         }
3182         break;
3183     case 11:
3184         /* data: {32'0, imm[7], ~{imm[6]}, 5{imm[6]}, imm[5:0], 19'0} */
3185         {
3186             uint64_t b6,b7;
3187             uint64_t t0, t1;
3188             b6 = (imm & 0x40) >> 6;
3189             b7 = (imm & 0x80) >> 7;
3190             t0 = (imm & 0x3f);
3191             t1 = (b7 << 6) | ((1-b6) << 5) | (b6 ? 0x1f : 0);
3192             data = (t1 << 25) | (t0 << 19);
3193         }
3194         break;
3195     case 12:
3196         /* data: {imm[7], ~imm[6], 8{imm[6]}, imm[5:0], 48'0} */
3197         {
3198             uint64_t b6,b7;
3199             uint64_t t0, t1;
3200             b6 = (imm & 0x40) >> 6;
3201             b7 = (imm & 0x80) >> 7;
3202             t0 = (imm & 0x3f);
3203             t1 = (b7 << 9) | ((1-b6) << 8) | (b6 ? 0xff : 0);
3204             data = (t1 << 54) | (t0 << 48);
3205         }
3206         break;
3207     default:
3208         generate_exception(ctx, EXCCODE_INE);
3209         g_assert_not_reached();
3210     }
3211     return data;
3214 static bool trans_vldi(DisasContext *ctx, arg_vldi *a)
3216     int sel, vece;
3217     uint64_t value;
3219     if (!avail_LSX(ctx)) {
3220         return false;
3221     }
3223     if (!check_vec(ctx, 16)) {
3224         return true;
3225     }
3227     sel = (a->imm >> 12) & 0x1;
3229     if (sel) {
3230         value = vldi_get_value(ctx, a->imm);
3231         vece = MO_64;
3232     } else {
3233         value = ((int32_t)(a->imm << 22)) >> 22;
3234         vece = (a->imm >> 10) & 0x3;
3235     }
3237     tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd), 16, ctx->vl/8,
3238                          tcg_constant_i64(value));
3239     return true;
3242 TRANS(vand_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_and)
3243 TRANS(vor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_or)
3244 TRANS(vxor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_xor)
3245 TRANS(vnor_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_nor)
3247 static bool trans_vandn_v(DisasContext *ctx, arg_vvv *a)
3249     uint32_t vd_ofs, vj_ofs, vk_ofs;
3251     if (!avail_LSX(ctx)) {
3252         return false;
3253     }
3255     if (!check_vec(ctx, 16)) {
3256         return true;
3257     }
3259     vd_ofs = vec_full_offset(a->vd);
3260     vj_ofs = vec_full_offset(a->vj);
3261     vk_ofs = vec_full_offset(a->vk);
3263     tcg_gen_gvec_andc(MO_64, vd_ofs, vk_ofs, vj_ofs, 16, ctx->vl/8);
3264     return true;
3266 TRANS(vorn_v, LSX, gvec_vvv, MO_64, tcg_gen_gvec_orc)
3267 TRANS(vandi_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_andi)
3268 TRANS(vori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_ori)
3269 TRANS(vxori_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_xori)
3271 static void gen_vnori(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3273     TCGv_vec t1;
3275     t1 = tcg_constant_vec_matching(t, vece, imm);
3276     tcg_gen_nor_vec(vece, t, a, t1);
3279 static void gen_vnori_b(TCGv_i64 t, TCGv_i64 a, int64_t imm)
3281     tcg_gen_movi_i64(t, dup_const(MO_8, imm));
3282     tcg_gen_nor_i64(t, a, t);
3285 static void do_vnori_b(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3286                        int64_t imm, uint32_t oprsz, uint32_t maxsz)
3288     static const TCGOpcode vecop_list[] = {
3289         INDEX_op_nor_vec, 0
3290         };
3291     static const GVecGen2i op = {
3292        .fni8 = gen_vnori_b,
3293        .fniv = gen_vnori,
3294        .fnoi = gen_helper_vnori_b,
3295        .opt_opc = vecop_list,
3296        .vece = MO_8
3297     };
3299     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op);
3302 TRANS(vnori_b, LSX, gvec_vv_i, MO_8, do_vnori_b)
3304 TRANS(vsll_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_shlv)
3305 TRANS(vsll_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_shlv)
3306 TRANS(vsll_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_shlv)
3307 TRANS(vsll_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_shlv)
3308 TRANS(vslli_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_shli)
3309 TRANS(vslli_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_shli)
3310 TRANS(vslli_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_shli)
3311 TRANS(vslli_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_shli)
3313 TRANS(vsrl_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_shrv)
3314 TRANS(vsrl_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_shrv)
3315 TRANS(vsrl_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_shrv)
3316 TRANS(vsrl_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_shrv)
3317 TRANS(vsrli_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_shri)
3318 TRANS(vsrli_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_shri)
3319 TRANS(vsrli_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_shri)
3320 TRANS(vsrli_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_shri)
3322 TRANS(vsra_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_sarv)
3323 TRANS(vsra_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_sarv)
3324 TRANS(vsra_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_sarv)
3325 TRANS(vsra_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_sarv)
3326 TRANS(vsrai_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_sari)
3327 TRANS(vsrai_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_sari)
3328 TRANS(vsrai_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_sari)
3329 TRANS(vsrai_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_sari)
3331 TRANS(vrotr_b, LSX, gvec_vvv, MO_8, tcg_gen_gvec_rotrv)
3332 TRANS(vrotr_h, LSX, gvec_vvv, MO_16, tcg_gen_gvec_rotrv)
3333 TRANS(vrotr_w, LSX, gvec_vvv, MO_32, tcg_gen_gvec_rotrv)
3334 TRANS(vrotr_d, LSX, gvec_vvv, MO_64, tcg_gen_gvec_rotrv)
3335 TRANS(vrotri_b, LSX, gvec_vv_i, MO_8, tcg_gen_gvec_rotri)
3336 TRANS(vrotri_h, LSX, gvec_vv_i, MO_16, tcg_gen_gvec_rotri)
3337 TRANS(vrotri_w, LSX, gvec_vv_i, MO_32, tcg_gen_gvec_rotri)
3338 TRANS(vrotri_d, LSX, gvec_vv_i, MO_64, tcg_gen_gvec_rotri)
3340 TRANS(vsllwil_h_b, LSX, gen_vv_i, gen_helper_vsllwil_h_b)
3341 TRANS(vsllwil_w_h, LSX, gen_vv_i, gen_helper_vsllwil_w_h)
3342 TRANS(vsllwil_d_w, LSX, gen_vv_i, gen_helper_vsllwil_d_w)
3343 TRANS(vextl_q_d, LSX, gen_vv, gen_helper_vextl_q_d)
3344 TRANS(vsllwil_hu_bu, LSX, gen_vv_i, gen_helper_vsllwil_hu_bu)
3345 TRANS(vsllwil_wu_hu, LSX, gen_vv_i, gen_helper_vsllwil_wu_hu)
3346 TRANS(vsllwil_du_wu, LSX, gen_vv_i, gen_helper_vsllwil_du_wu)
3347 TRANS(vextl_qu_du, LSX, gen_vv, gen_helper_vextl_qu_du)
3349 TRANS(vsrlr_b, LSX, gen_vvv, gen_helper_vsrlr_b)
3350 TRANS(vsrlr_h, LSX, gen_vvv, gen_helper_vsrlr_h)
3351 TRANS(vsrlr_w, LSX, gen_vvv, gen_helper_vsrlr_w)
3352 TRANS(vsrlr_d, LSX, gen_vvv, gen_helper_vsrlr_d)
3353 TRANS(vsrlri_b, LSX, gen_vv_i, gen_helper_vsrlri_b)
3354 TRANS(vsrlri_h, LSX, gen_vv_i, gen_helper_vsrlri_h)
3355 TRANS(vsrlri_w, LSX, gen_vv_i, gen_helper_vsrlri_w)
3356 TRANS(vsrlri_d, LSX, gen_vv_i, gen_helper_vsrlri_d)
3358 TRANS(vsrar_b, LSX, gen_vvv, gen_helper_vsrar_b)
3359 TRANS(vsrar_h, LSX, gen_vvv, gen_helper_vsrar_h)
3360 TRANS(vsrar_w, LSX, gen_vvv, gen_helper_vsrar_w)
3361 TRANS(vsrar_d, LSX, gen_vvv, gen_helper_vsrar_d)
3362 TRANS(vsrari_b, LSX, gen_vv_i, gen_helper_vsrari_b)
3363 TRANS(vsrari_h, LSX, gen_vv_i, gen_helper_vsrari_h)
3364 TRANS(vsrari_w, LSX, gen_vv_i, gen_helper_vsrari_w)
3365 TRANS(vsrari_d, LSX, gen_vv_i, gen_helper_vsrari_d)
3367 TRANS(vsrln_b_h, LSX, gen_vvv, gen_helper_vsrln_b_h)
3368 TRANS(vsrln_h_w, LSX, gen_vvv, gen_helper_vsrln_h_w)
3369 TRANS(vsrln_w_d, LSX, gen_vvv, gen_helper_vsrln_w_d)
3370 TRANS(vsran_b_h, LSX, gen_vvv, gen_helper_vsran_b_h)
3371 TRANS(vsran_h_w, LSX, gen_vvv, gen_helper_vsran_h_w)
3372 TRANS(vsran_w_d, LSX, gen_vvv, gen_helper_vsran_w_d)
3374 TRANS(vsrlni_b_h, LSX, gen_vv_i, gen_helper_vsrlni_b_h)
3375 TRANS(vsrlni_h_w, LSX, gen_vv_i, gen_helper_vsrlni_h_w)
3376 TRANS(vsrlni_w_d, LSX, gen_vv_i, gen_helper_vsrlni_w_d)
3377 TRANS(vsrlni_d_q, LSX, gen_vv_i, gen_helper_vsrlni_d_q)
3378 TRANS(vsrani_b_h, LSX, gen_vv_i, gen_helper_vsrani_b_h)
3379 TRANS(vsrani_h_w, LSX, gen_vv_i, gen_helper_vsrani_h_w)
3380 TRANS(vsrani_w_d, LSX, gen_vv_i, gen_helper_vsrani_w_d)
3381 TRANS(vsrani_d_q, LSX, gen_vv_i, gen_helper_vsrani_d_q)
3383 TRANS(vsrlrn_b_h, LSX, gen_vvv, gen_helper_vsrlrn_b_h)
3384 TRANS(vsrlrn_h_w, LSX, gen_vvv, gen_helper_vsrlrn_h_w)
3385 TRANS(vsrlrn_w_d, LSX, gen_vvv, gen_helper_vsrlrn_w_d)
3386 TRANS(vsrarn_b_h, LSX, gen_vvv, gen_helper_vsrarn_b_h)
3387 TRANS(vsrarn_h_w, LSX, gen_vvv, gen_helper_vsrarn_h_w)
3388 TRANS(vsrarn_w_d, LSX, gen_vvv, gen_helper_vsrarn_w_d)
3390 TRANS(vsrlrni_b_h, LSX, gen_vv_i, gen_helper_vsrlrni_b_h)
3391 TRANS(vsrlrni_h_w, LSX, gen_vv_i, gen_helper_vsrlrni_h_w)
3392 TRANS(vsrlrni_w_d, LSX, gen_vv_i, gen_helper_vsrlrni_w_d)
3393 TRANS(vsrlrni_d_q, LSX, gen_vv_i, gen_helper_vsrlrni_d_q)
3394 TRANS(vsrarni_b_h, LSX, gen_vv_i, gen_helper_vsrarni_b_h)
3395 TRANS(vsrarni_h_w, LSX, gen_vv_i, gen_helper_vsrarni_h_w)
3396 TRANS(vsrarni_w_d, LSX, gen_vv_i, gen_helper_vsrarni_w_d)
3397 TRANS(vsrarni_d_q, LSX, gen_vv_i, gen_helper_vsrarni_d_q)
3399 TRANS(vssrln_b_h, LSX, gen_vvv, gen_helper_vssrln_b_h)
3400 TRANS(vssrln_h_w, LSX, gen_vvv, gen_helper_vssrln_h_w)
3401 TRANS(vssrln_w_d, LSX, gen_vvv, gen_helper_vssrln_w_d)
3402 TRANS(vssran_b_h, LSX, gen_vvv, gen_helper_vssran_b_h)
3403 TRANS(vssran_h_w, LSX, gen_vvv, gen_helper_vssran_h_w)
3404 TRANS(vssran_w_d, LSX, gen_vvv, gen_helper_vssran_w_d)
3405 TRANS(vssrln_bu_h, LSX, gen_vvv, gen_helper_vssrln_bu_h)
3406 TRANS(vssrln_hu_w, LSX, gen_vvv, gen_helper_vssrln_hu_w)
3407 TRANS(vssrln_wu_d, LSX, gen_vvv, gen_helper_vssrln_wu_d)
3408 TRANS(vssran_bu_h, LSX, gen_vvv, gen_helper_vssran_bu_h)
3409 TRANS(vssran_hu_w, LSX, gen_vvv, gen_helper_vssran_hu_w)
3410 TRANS(vssran_wu_d, LSX, gen_vvv, gen_helper_vssran_wu_d)
3412 TRANS(vssrlni_b_h, LSX, gen_vv_i, gen_helper_vssrlni_b_h)
3413 TRANS(vssrlni_h_w, LSX, gen_vv_i, gen_helper_vssrlni_h_w)
3414 TRANS(vssrlni_w_d, LSX, gen_vv_i, gen_helper_vssrlni_w_d)
3415 TRANS(vssrlni_d_q, LSX, gen_vv_i, gen_helper_vssrlni_d_q)
3416 TRANS(vssrani_b_h, LSX, gen_vv_i, gen_helper_vssrani_b_h)
3417 TRANS(vssrani_h_w, LSX, gen_vv_i, gen_helper_vssrani_h_w)
3418 TRANS(vssrani_w_d, LSX, gen_vv_i, gen_helper_vssrani_w_d)
3419 TRANS(vssrani_d_q, LSX, gen_vv_i, gen_helper_vssrani_d_q)
3420 TRANS(vssrlni_bu_h, LSX, gen_vv_i, gen_helper_vssrlni_bu_h)
3421 TRANS(vssrlni_hu_w, LSX, gen_vv_i, gen_helper_vssrlni_hu_w)
3422 TRANS(vssrlni_wu_d, LSX, gen_vv_i, gen_helper_vssrlni_wu_d)
3423 TRANS(vssrlni_du_q, LSX, gen_vv_i, gen_helper_vssrlni_du_q)
3424 TRANS(vssrani_bu_h, LSX, gen_vv_i, gen_helper_vssrani_bu_h)
3425 TRANS(vssrani_hu_w, LSX, gen_vv_i, gen_helper_vssrani_hu_w)
3426 TRANS(vssrani_wu_d, LSX, gen_vv_i, gen_helper_vssrani_wu_d)
3427 TRANS(vssrani_du_q, LSX, gen_vv_i, gen_helper_vssrani_du_q)
3429 TRANS(vssrlrn_b_h, LSX, gen_vvv, gen_helper_vssrlrn_b_h)
3430 TRANS(vssrlrn_h_w, LSX, gen_vvv, gen_helper_vssrlrn_h_w)
3431 TRANS(vssrlrn_w_d, LSX, gen_vvv, gen_helper_vssrlrn_w_d)
3432 TRANS(vssrarn_b_h, LSX, gen_vvv, gen_helper_vssrarn_b_h)
3433 TRANS(vssrarn_h_w, LSX, gen_vvv, gen_helper_vssrarn_h_w)
3434 TRANS(vssrarn_w_d, LSX, gen_vvv, gen_helper_vssrarn_w_d)
3435 TRANS(vssrlrn_bu_h, LSX, gen_vvv, gen_helper_vssrlrn_bu_h)
3436 TRANS(vssrlrn_hu_w, LSX, gen_vvv, gen_helper_vssrlrn_hu_w)
3437 TRANS(vssrlrn_wu_d, LSX, gen_vvv, gen_helper_vssrlrn_wu_d)
3438 TRANS(vssrarn_bu_h, LSX, gen_vvv, gen_helper_vssrarn_bu_h)
3439 TRANS(vssrarn_hu_w, LSX, gen_vvv, gen_helper_vssrarn_hu_w)
3440 TRANS(vssrarn_wu_d, LSX, gen_vvv, gen_helper_vssrarn_wu_d)
3442 TRANS(vssrlrni_b_h, LSX, gen_vv_i, gen_helper_vssrlrni_b_h)
3443 TRANS(vssrlrni_h_w, LSX, gen_vv_i, gen_helper_vssrlrni_h_w)
3444 TRANS(vssrlrni_w_d, LSX, gen_vv_i, gen_helper_vssrlrni_w_d)
3445 TRANS(vssrlrni_d_q, LSX, gen_vv_i, gen_helper_vssrlrni_d_q)
3446 TRANS(vssrarni_b_h, LSX, gen_vv_i, gen_helper_vssrarni_b_h)
3447 TRANS(vssrarni_h_w, LSX, gen_vv_i, gen_helper_vssrarni_h_w)
3448 TRANS(vssrarni_w_d, LSX, gen_vv_i, gen_helper_vssrarni_w_d)
3449 TRANS(vssrarni_d_q, LSX, gen_vv_i, gen_helper_vssrarni_d_q)
3450 TRANS(vssrlrni_bu_h, LSX, gen_vv_i, gen_helper_vssrlrni_bu_h)
3451 TRANS(vssrlrni_hu_w, LSX, gen_vv_i, gen_helper_vssrlrni_hu_w)
3452 TRANS(vssrlrni_wu_d, LSX, gen_vv_i, gen_helper_vssrlrni_wu_d)
3453 TRANS(vssrlrni_du_q, LSX, gen_vv_i, gen_helper_vssrlrni_du_q)
3454 TRANS(vssrarni_bu_h, LSX, gen_vv_i, gen_helper_vssrarni_bu_h)
3455 TRANS(vssrarni_hu_w, LSX, gen_vv_i, gen_helper_vssrarni_hu_w)
3456 TRANS(vssrarni_wu_d, LSX, gen_vv_i, gen_helper_vssrarni_wu_d)
3457 TRANS(vssrarni_du_q, LSX, gen_vv_i, gen_helper_vssrarni_du_q)
3459 TRANS(vclo_b, LSX, gen_vv, gen_helper_vclo_b)
3460 TRANS(vclo_h, LSX, gen_vv, gen_helper_vclo_h)
3461 TRANS(vclo_w, LSX, gen_vv, gen_helper_vclo_w)
3462 TRANS(vclo_d, LSX, gen_vv, gen_helper_vclo_d)
3463 TRANS(vclz_b, LSX, gen_vv, gen_helper_vclz_b)
3464 TRANS(vclz_h, LSX, gen_vv, gen_helper_vclz_h)
3465 TRANS(vclz_w, LSX, gen_vv, gen_helper_vclz_w)
3466 TRANS(vclz_d, LSX, gen_vv, gen_helper_vclz_d)
3468 TRANS(vpcnt_b, LSX, gen_vv, gen_helper_vpcnt_b)
3469 TRANS(vpcnt_h, LSX, gen_vv, gen_helper_vpcnt_h)
3470 TRANS(vpcnt_w, LSX, gen_vv, gen_helper_vpcnt_w)
3471 TRANS(vpcnt_d, LSX, gen_vv, gen_helper_vpcnt_d)
3473 static void do_vbit(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
3474                     void (*func)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
3476     TCGv_vec mask, lsh, t1, one;
3478     lsh = tcg_temp_new_vec_matching(t);
3479     t1 = tcg_temp_new_vec_matching(t);
3480     mask = tcg_constant_vec_matching(t, vece, (8 << vece) - 1);
3481     one = tcg_constant_vec_matching(t, vece, 1);
3483     tcg_gen_and_vec(vece, lsh, b, mask);
3484     tcg_gen_shlv_vec(vece, t1, one, lsh);
3485     func(vece, t, a, t1);
3488 static void gen_vbitclr(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
3490     do_vbit(vece, t, a, b, tcg_gen_andc_vec);
3493 static void gen_vbitset(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
3495     do_vbit(vece, t, a, b, tcg_gen_or_vec);
3498 static void gen_vbitrev(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
3500     do_vbit(vece, t, a, b, tcg_gen_xor_vec);
3503 static void do_vbitclr(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3504                       uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
3506     static const TCGOpcode vecop_list[] = {
3507         INDEX_op_shlv_vec, INDEX_op_andc_vec, 0
3508         };
3509     static const GVecGen3 op[4] = {
3510         {
3511             .fniv = gen_vbitclr,
3512             .fno = gen_helper_vbitclr_b,
3513             .opt_opc = vecop_list,
3514             .vece = MO_8
3515         },
3516         {
3517             .fniv = gen_vbitclr,
3518             .fno = gen_helper_vbitclr_h,
3519             .opt_opc = vecop_list,
3520             .vece = MO_16
3521         },
3522         {
3523             .fniv = gen_vbitclr,
3524             .fno = gen_helper_vbitclr_w,
3525             .opt_opc = vecop_list,
3526             .vece = MO_32
3527         },
3528         {
3529             .fniv = gen_vbitclr,
3530             .fno = gen_helper_vbitclr_d,
3531             .opt_opc = vecop_list,
3532             .vece = MO_64
3533         },
3534     };
3536     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
3539 TRANS(vbitclr_b, LSX, gvec_vvv, MO_8, do_vbitclr)
3540 TRANS(vbitclr_h, LSX, gvec_vvv, MO_16, do_vbitclr)
3541 TRANS(vbitclr_w, LSX, gvec_vvv, MO_32, do_vbitclr)
3542 TRANS(vbitclr_d, LSX, gvec_vvv, MO_64, do_vbitclr)
3544 static void do_vbiti(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm,
3545                      void (*func)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
3547     int lsh;
3548     TCGv_vec t1, one;
3550     lsh = imm & ((8 << vece) -1);
3551     t1 = tcg_temp_new_vec_matching(t);
3552     one = tcg_constant_vec_matching(t, vece, 1);
3554     tcg_gen_shli_vec(vece, t1, one, lsh);
3555     func(vece, t, a, t1);
3558 static void gen_vbitclri(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3560     do_vbiti(vece, t, a, imm, tcg_gen_andc_vec);
3563 static void gen_vbitseti(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3565     do_vbiti(vece, t, a, imm, tcg_gen_or_vec);
3568 static void gen_vbitrevi(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3570     do_vbiti(vece, t, a, imm, tcg_gen_xor_vec);
3573 static void do_vbitclri(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3574                         int64_t imm, uint32_t oprsz, uint32_t maxsz)
3576     static const TCGOpcode vecop_list[] = {
3577         INDEX_op_shli_vec, INDEX_op_andc_vec, 0
3578         };
3579     static const GVecGen2i op[4] = {
3580         {
3581             .fniv = gen_vbitclri,
3582             .fnoi = gen_helper_vbitclri_b,
3583             .opt_opc = vecop_list,
3584             .vece = MO_8
3585         },
3586         {
3587             .fniv = gen_vbitclri,
3588             .fnoi = gen_helper_vbitclri_h,
3589             .opt_opc = vecop_list,
3590             .vece = MO_16
3591         },
3592         {
3593             .fniv = gen_vbitclri,
3594             .fnoi = gen_helper_vbitclri_w,
3595             .opt_opc = vecop_list,
3596             .vece = MO_32
3597         },
3598         {
3599             .fniv = gen_vbitclri,
3600             .fnoi = gen_helper_vbitclri_d,
3601             .opt_opc = vecop_list,
3602             .vece = MO_64
3603         },
3604     };
3606     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
3609 TRANS(vbitclri_b, LSX, gvec_vv_i, MO_8, do_vbitclri)
3610 TRANS(vbitclri_h, LSX, gvec_vv_i, MO_16, do_vbitclri)
3611 TRANS(vbitclri_w, LSX, gvec_vv_i, MO_32, do_vbitclri)
3612 TRANS(vbitclri_d, LSX, gvec_vv_i, MO_64, do_vbitclri)
3614 static void do_vbitset(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3615                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
3617     static const TCGOpcode vecop_list[] = {
3618         INDEX_op_shlv_vec, 0
3619         };
3620     static const GVecGen3 op[4] = {
3621         {
3622             .fniv = gen_vbitset,
3623             .fno = gen_helper_vbitset_b,
3624             .opt_opc = vecop_list,
3625             .vece = MO_8
3626         },
3627         {
3628             .fniv = gen_vbitset,
3629             .fno = gen_helper_vbitset_h,
3630             .opt_opc = vecop_list,
3631             .vece = MO_16
3632         },
3633         {
3634             .fniv = gen_vbitset,
3635             .fno = gen_helper_vbitset_w,
3636             .opt_opc = vecop_list,
3637             .vece = MO_32
3638         },
3639         {
3640             .fniv = gen_vbitset,
3641             .fno = gen_helper_vbitset_d,
3642             .opt_opc = vecop_list,
3643             .vece = MO_64
3644         },
3645     };
3647     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
3650 TRANS(vbitset_b, LSX, gvec_vvv, MO_8, do_vbitset)
3651 TRANS(vbitset_h, LSX, gvec_vvv, MO_16, do_vbitset)
3652 TRANS(vbitset_w, LSX, gvec_vvv, MO_32, do_vbitset)
3653 TRANS(vbitset_d, LSX, gvec_vvv, MO_64, do_vbitset)
3655 static void do_vbitseti(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3656                         int64_t imm, uint32_t oprsz, uint32_t maxsz)
3658     static const TCGOpcode vecop_list[] = {
3659         INDEX_op_shli_vec, 0
3660         };
3661     static const GVecGen2i op[4] = {
3662         {
3663             .fniv = gen_vbitseti,
3664             .fnoi = gen_helper_vbitseti_b,
3665             .opt_opc = vecop_list,
3666             .vece = MO_8
3667         },
3668         {
3669             .fniv = gen_vbitseti,
3670             .fnoi = gen_helper_vbitseti_h,
3671             .opt_opc = vecop_list,
3672             .vece = MO_16
3673         },
3674         {
3675             .fniv = gen_vbitseti,
3676             .fnoi = gen_helper_vbitseti_w,
3677             .opt_opc = vecop_list,
3678             .vece = MO_32
3679         },
3680         {
3681             .fniv = gen_vbitseti,
3682             .fnoi = gen_helper_vbitseti_d,
3683             .opt_opc = vecop_list,
3684             .vece = MO_64
3685         },
3686     };
3688     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
3691 TRANS(vbitseti_b, LSX, gvec_vv_i, MO_8, do_vbitseti)
3692 TRANS(vbitseti_h, LSX, gvec_vv_i, MO_16, do_vbitseti)
3693 TRANS(vbitseti_w, LSX, gvec_vv_i, MO_32, do_vbitseti)
3694 TRANS(vbitseti_d, LSX, gvec_vv_i, MO_64, do_vbitseti)
3696 static void do_vbitrev(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3697                        uint32_t vk_ofs, uint32_t oprsz, uint32_t maxsz)
3699     static const TCGOpcode vecop_list[] = {
3700         INDEX_op_shlv_vec, 0
3701         };
3702     static const GVecGen3 op[4] = {
3703         {
3704             .fniv = gen_vbitrev,
3705             .fno = gen_helper_vbitrev_b,
3706             .opt_opc = vecop_list,
3707             .vece = MO_8
3708         },
3709         {
3710             .fniv = gen_vbitrev,
3711             .fno = gen_helper_vbitrev_h,
3712             .opt_opc = vecop_list,
3713             .vece = MO_16
3714         },
3715         {
3716             .fniv = gen_vbitrev,
3717             .fno = gen_helper_vbitrev_w,
3718             .opt_opc = vecop_list,
3719             .vece = MO_32
3720         },
3721         {
3722             .fniv = gen_vbitrev,
3723             .fno = gen_helper_vbitrev_d,
3724             .opt_opc = vecop_list,
3725             .vece = MO_64
3726         },
3727     };
3729     tcg_gen_gvec_3(vd_ofs, vj_ofs, vk_ofs, oprsz, maxsz, &op[vece]);
3732 TRANS(vbitrev_b, LSX, gvec_vvv, MO_8, do_vbitrev)
3733 TRANS(vbitrev_h, LSX, gvec_vvv, MO_16, do_vbitrev)
3734 TRANS(vbitrev_w, LSX, gvec_vvv, MO_32, do_vbitrev)
3735 TRANS(vbitrev_d, LSX, gvec_vvv, MO_64, do_vbitrev)
3737 static void do_vbitrevi(unsigned vece, uint32_t vd_ofs, uint32_t vj_ofs,
3738                         int64_t imm, uint32_t oprsz, uint32_t maxsz)
3740     static const TCGOpcode vecop_list[] = {
3741         INDEX_op_shli_vec, 0
3742         };
3743     static const GVecGen2i op[4] = {
3744         {
3745             .fniv = gen_vbitrevi,
3746             .fnoi = gen_helper_vbitrevi_b,
3747             .opt_opc = vecop_list,
3748             .vece = MO_8
3749         },
3750         {
3751             .fniv = gen_vbitrevi,
3752             .fnoi = gen_helper_vbitrevi_h,
3753             .opt_opc = vecop_list,
3754             .vece = MO_16
3755         },
3756         {
3757             .fniv = gen_vbitrevi,
3758             .fnoi = gen_helper_vbitrevi_w,
3759             .opt_opc = vecop_list,
3760             .vece = MO_32
3761         },
3762         {
3763             .fniv = gen_vbitrevi,
3764             .fnoi = gen_helper_vbitrevi_d,
3765             .opt_opc = vecop_list,
3766             .vece = MO_64
3767         },
3768     };
3770     tcg_gen_gvec_2i(vd_ofs, vj_ofs, oprsz, maxsz, imm, &op[vece]);
3773 TRANS(vbitrevi_b, LSX, gvec_vv_i, MO_8, do_vbitrevi)
3774 TRANS(vbitrevi_h, LSX, gvec_vv_i, MO_16, do_vbitrevi)
3775 TRANS(vbitrevi_w, LSX, gvec_vv_i, MO_32, do_vbitrevi)
3776 TRANS(vbitrevi_d, LSX, gvec_vv_i, MO_64, do_vbitrevi)
3778 TRANS(vfrstp_b, LSX, gen_vvv, gen_helper_vfrstp_b)
3779 TRANS(vfrstp_h, LSX, gen_vvv, gen_helper_vfrstp_h)
3780 TRANS(vfrstpi_b, LSX, gen_vv_i, gen_helper_vfrstpi_b)
3781 TRANS(vfrstpi_h, LSX, gen_vv_i, gen_helper_vfrstpi_h)
3783 TRANS(vfadd_s, LSX, gen_vvv_ptr, gen_helper_vfadd_s)
3784 TRANS(vfadd_d, LSX, gen_vvv_ptr, gen_helper_vfadd_d)
3785 TRANS(vfsub_s, LSX, gen_vvv_ptr, gen_helper_vfsub_s)
3786 TRANS(vfsub_d, LSX, gen_vvv_ptr, gen_helper_vfsub_d)
3787 TRANS(vfmul_s, LSX, gen_vvv_ptr, gen_helper_vfmul_s)
3788 TRANS(vfmul_d, LSX, gen_vvv_ptr, gen_helper_vfmul_d)
3789 TRANS(vfdiv_s, LSX, gen_vvv_ptr, gen_helper_vfdiv_s)
3790 TRANS(vfdiv_d, LSX, gen_vvv_ptr, gen_helper_vfdiv_d)
3792 TRANS(vfmadd_s, LSX, gen_vvvv_ptr, gen_helper_vfmadd_s)
3793 TRANS(vfmadd_d, LSX, gen_vvvv_ptr, gen_helper_vfmadd_d)
3794 TRANS(vfmsub_s, LSX, gen_vvvv_ptr, gen_helper_vfmsub_s)
3795 TRANS(vfmsub_d, LSX, gen_vvvv_ptr, gen_helper_vfmsub_d)
3796 TRANS(vfnmadd_s, LSX, gen_vvvv_ptr, gen_helper_vfnmadd_s)
3797 TRANS(vfnmadd_d, LSX, gen_vvvv_ptr, gen_helper_vfnmadd_d)
3798 TRANS(vfnmsub_s, LSX, gen_vvvv_ptr, gen_helper_vfnmsub_s)
3799 TRANS(vfnmsub_d, LSX, gen_vvvv_ptr, gen_helper_vfnmsub_d)
3801 TRANS(vfmax_s, LSX, gen_vvv_ptr, gen_helper_vfmax_s)
3802 TRANS(vfmax_d, LSX, gen_vvv_ptr, gen_helper_vfmax_d)
3803 TRANS(vfmin_s, LSX, gen_vvv_ptr, gen_helper_vfmin_s)
3804 TRANS(vfmin_d, LSX, gen_vvv_ptr, gen_helper_vfmin_d)
3806 TRANS(vfmaxa_s, LSX, gen_vvv_ptr, gen_helper_vfmaxa_s)
3807 TRANS(vfmaxa_d, LSX, gen_vvv_ptr, gen_helper_vfmaxa_d)
3808 TRANS(vfmina_s, LSX, gen_vvv_ptr, gen_helper_vfmina_s)
3809 TRANS(vfmina_d, LSX, gen_vvv_ptr, gen_helper_vfmina_d)
3811 TRANS(vflogb_s, LSX, gen_vv_ptr, gen_helper_vflogb_s)
3812 TRANS(vflogb_d, LSX, gen_vv_ptr, gen_helper_vflogb_d)
3814 TRANS(vfclass_s, LSX, gen_vv_ptr, gen_helper_vfclass_s)
3815 TRANS(vfclass_d, LSX, gen_vv_ptr, gen_helper_vfclass_d)
3817 TRANS(vfsqrt_s, LSX, gen_vv_ptr, gen_helper_vfsqrt_s)
3818 TRANS(vfsqrt_d, LSX, gen_vv_ptr, gen_helper_vfsqrt_d)
3819 TRANS(vfrecip_s, LSX, gen_vv_ptr, gen_helper_vfrecip_s)
3820 TRANS(vfrecip_d, LSX, gen_vv_ptr, gen_helper_vfrecip_d)
3821 TRANS(vfrsqrt_s, LSX, gen_vv_ptr, gen_helper_vfrsqrt_s)
3822 TRANS(vfrsqrt_d, LSX, gen_vv_ptr, gen_helper_vfrsqrt_d)
3824 TRANS(vfcvtl_s_h, LSX, gen_vv_ptr, gen_helper_vfcvtl_s_h)
3825 TRANS(vfcvth_s_h, LSX, gen_vv_ptr, gen_helper_vfcvth_s_h)
3826 TRANS(vfcvtl_d_s, LSX, gen_vv_ptr, gen_helper_vfcvtl_d_s)
3827 TRANS(vfcvth_d_s, LSX, gen_vv_ptr, gen_helper_vfcvth_d_s)
3828 TRANS(vfcvt_h_s, LSX, gen_vvv_ptr, gen_helper_vfcvt_h_s)
3829 TRANS(vfcvt_s_d, LSX, gen_vvv_ptr, gen_helper_vfcvt_s_d)
3831 TRANS(vfrintrne_s, LSX, gen_vv_ptr, gen_helper_vfrintrne_s)
3832 TRANS(vfrintrne_d, LSX, gen_vv_ptr, gen_helper_vfrintrne_d)
3833 TRANS(vfrintrz_s, LSX, gen_vv_ptr, gen_helper_vfrintrz_s)
3834 TRANS(vfrintrz_d, LSX, gen_vv_ptr, gen_helper_vfrintrz_d)
3835 TRANS(vfrintrp_s, LSX, gen_vv_ptr, gen_helper_vfrintrp_s)
3836 TRANS(vfrintrp_d, LSX, gen_vv_ptr, gen_helper_vfrintrp_d)
3837 TRANS(vfrintrm_s, LSX, gen_vv_ptr, gen_helper_vfrintrm_s)
3838 TRANS(vfrintrm_d, LSX, gen_vv_ptr, gen_helper_vfrintrm_d)
3839 TRANS(vfrint_s, LSX, gen_vv_ptr, gen_helper_vfrint_s)
3840 TRANS(vfrint_d, LSX, gen_vv_ptr, gen_helper_vfrint_d)
3842 TRANS(vftintrne_w_s, LSX, gen_vv_ptr, gen_helper_vftintrne_w_s)
3843 TRANS(vftintrne_l_d, LSX, gen_vv_ptr, gen_helper_vftintrne_l_d)
3844 TRANS(vftintrz_w_s, LSX, gen_vv_ptr, gen_helper_vftintrz_w_s)
3845 TRANS(vftintrz_l_d, LSX, gen_vv_ptr, gen_helper_vftintrz_l_d)
3846 TRANS(vftintrp_w_s, LSX, gen_vv_ptr, gen_helper_vftintrp_w_s)
3847 TRANS(vftintrp_l_d, LSX, gen_vv_ptr, gen_helper_vftintrp_l_d)
3848 TRANS(vftintrm_w_s, LSX, gen_vv_ptr, gen_helper_vftintrm_w_s)
3849 TRANS(vftintrm_l_d, LSX, gen_vv_ptr, gen_helper_vftintrm_l_d)
3850 TRANS(vftint_w_s, LSX, gen_vv_ptr, gen_helper_vftint_w_s)
3851 TRANS(vftint_l_d, LSX, gen_vv_ptr, gen_helper_vftint_l_d)
3852 TRANS(vftintrz_wu_s, LSX, gen_vv_ptr, gen_helper_vftintrz_wu_s)
3853 TRANS(vftintrz_lu_d, LSX, gen_vv_ptr, gen_helper_vftintrz_lu_d)
3854 TRANS(vftint_wu_s, LSX, gen_vv_ptr, gen_helper_vftint_wu_s)
3855 TRANS(vftint_lu_d, LSX, gen_vv_ptr, gen_helper_vftint_lu_d)
3856 TRANS(vftintrne_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrne_w_d)
3857 TRANS(vftintrz_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrz_w_d)
3858 TRANS(vftintrp_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrp_w_d)
3859 TRANS(vftintrm_w_d, LSX, gen_vvv_ptr, gen_helper_vftintrm_w_d)
3860 TRANS(vftint_w_d, LSX, gen_vvv_ptr, gen_helper_vftint_w_d)
3861 TRANS(vftintrnel_l_s, LSX, gen_vv_ptr, gen_helper_vftintrnel_l_s)
3862 TRANS(vftintrneh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrneh_l_s)
3863 TRANS(vftintrzl_l_s, LSX, gen_vv_ptr, gen_helper_vftintrzl_l_s)
3864 TRANS(vftintrzh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrzh_l_s)
3865 TRANS(vftintrpl_l_s, LSX, gen_vv_ptr, gen_helper_vftintrpl_l_s)
3866 TRANS(vftintrph_l_s, LSX, gen_vv_ptr, gen_helper_vftintrph_l_s)
3867 TRANS(vftintrml_l_s, LSX, gen_vv_ptr, gen_helper_vftintrml_l_s)
3868 TRANS(vftintrmh_l_s, LSX, gen_vv_ptr, gen_helper_vftintrmh_l_s)
3869 TRANS(vftintl_l_s, LSX, gen_vv_ptr, gen_helper_vftintl_l_s)
3870 TRANS(vftinth_l_s, LSX, gen_vv_ptr, gen_helper_vftinth_l_s)
3872 TRANS(vffint_s_w, LSX, gen_vv_ptr, gen_helper_vffint_s_w)
3873 TRANS(vffint_d_l, LSX, gen_vv_ptr, gen_helper_vffint_d_l)
3874 TRANS(vffint_s_wu, LSX, gen_vv_ptr, gen_helper_vffint_s_wu)
3875 TRANS(vffint_d_lu, LSX, gen_vv_ptr, gen_helper_vffint_d_lu)
3876 TRANS(vffintl_d_w, LSX, gen_vv_ptr, gen_helper_vffintl_d_w)
3877 TRANS(vffinth_d_w, LSX, gen_vv_ptr, gen_helper_vffinth_d_w)
3878 TRANS(vffint_s_l, LSX, gen_vvv_ptr, gen_helper_vffint_s_l)
3880 static bool do_cmp(DisasContext *ctx, arg_vvv *a, MemOp mop, TCGCond cond)
3882     uint32_t vd_ofs, vj_ofs, vk_ofs;
3884     if (!check_vec(ctx, 16)) {
3885         return true;
3886     }
3888     vd_ofs = vec_full_offset(a->vd);
3889     vj_ofs = vec_full_offset(a->vj);
3890     vk_ofs = vec_full_offset(a->vk);
3892     tcg_gen_gvec_cmp(cond, mop, vd_ofs, vj_ofs, vk_ofs, 16, ctx->vl/8);
3893     return true;
3896 static void do_cmpi_vec(TCGCond cond,
3897                         unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3899     tcg_gen_cmp_vec(cond, vece, t, a, tcg_constant_vec_matching(t, vece, imm));
3902 static void gen_vseqi_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3904     do_cmpi_vec(TCG_COND_EQ, vece, t, a, imm);
3907 static void gen_vslei_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3909     do_cmpi_vec(TCG_COND_LE, vece, t, a, imm);
3912 static void gen_vslti_s_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3914     do_cmpi_vec(TCG_COND_LT, vece, t, a, imm);
3917 static void gen_vslei_u_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3919     do_cmpi_vec(TCG_COND_LEU, vece, t, a, imm);
3922 static void gen_vslti_u_vec(unsigned vece, TCGv_vec t, TCGv_vec a, int64_t imm)
3924     do_cmpi_vec(TCG_COND_LTU, vece, t, a, imm);
3927 #define DO_CMPI_S(NAME)                                                \
3928 static bool do_## NAME ##_s(DisasContext *ctx, arg_vv_i *a, MemOp mop) \
3929 {                                                                      \
3930     uint32_t vd_ofs, vj_ofs;                                           \
3931                                                                        \
3932     if (!check_vec(ctx, 16)) {                                         \
3933         return true;                                                   \
3934     }                                                                  \
3935                                                                        \
3936     static const TCGOpcode vecop_list[] = {                            \
3937         INDEX_op_cmp_vec, 0                                            \
3938     };                                                                 \
3939     static const GVecGen2i op[4] = {                                   \
3940         {                                                              \
3941             .fniv = gen_## NAME ##_s_vec,                              \
3942             .fnoi = gen_helper_## NAME ##_b,                           \
3943             .opt_opc = vecop_list,                                     \
3944             .vece = MO_8                                               \
3945         },                                                             \
3946         {                                                              \
3947             .fniv = gen_## NAME ##_s_vec,                              \
3948             .fnoi = gen_helper_## NAME ##_h,                           \
3949             .opt_opc = vecop_list,                                     \
3950             .vece = MO_16                                              \
3951         },                                                             \
3952         {                                                              \
3953             .fniv = gen_## NAME ##_s_vec,                              \
3954             .fnoi = gen_helper_## NAME ##_w,                           \
3955             .opt_opc = vecop_list,                                     \
3956             .vece = MO_32                                              \
3957         },                                                             \
3958         {                                                              \
3959             .fniv = gen_## NAME ##_s_vec,                              \
3960             .fnoi = gen_helper_## NAME ##_d,                           \
3961             .opt_opc = vecop_list,                                     \
3962             .vece = MO_64                                              \
3963         }                                                              \
3964     };                                                                 \
3965                                                                        \
3966     vd_ofs = vec_full_offset(a->vd);                                   \
3967     vj_ofs = vec_full_offset(a->vj);                                   \
3968                                                                        \
3969     tcg_gen_gvec_2i(vd_ofs, vj_ofs, 16, ctx->vl/8, a->imm, &op[mop]);  \
3970                                                                        \
3971     return true;                                                       \
3974 DO_CMPI_S(vseqi)
3975 DO_CMPI_S(vslei)
3976 DO_CMPI_S(vslti)
3978 #define DO_CMPI_U(NAME)                                                \
3979 static bool do_## NAME ##_u(DisasContext *ctx, arg_vv_i *a, MemOp mop) \
3980 {                                                                      \
3981     uint32_t vd_ofs, vj_ofs;                                           \
3982                                                                        \
3983     if (!check_vec(ctx, 16)) {                                         \
3984         return true;                                                   \
3985     }                                                                  \
3986                                                                        \
3987     static const TCGOpcode vecop_list[] = {                            \
3988         INDEX_op_cmp_vec, 0                                            \
3989     };                                                                 \
3990     static const GVecGen2i op[4] = {                                   \
3991         {                                                              \
3992             .fniv = gen_## NAME ##_u_vec,                              \
3993             .fnoi = gen_helper_## NAME ##_bu,                          \
3994             .opt_opc = vecop_list,                                     \
3995             .vece = MO_8                                               \
3996         },                                                             \
3997         {                                                              \
3998             .fniv = gen_## NAME ##_u_vec,                              \
3999             .fnoi = gen_helper_## NAME ##_hu,                          \
4000             .opt_opc = vecop_list,                                     \
4001             .vece = MO_16                                              \
4002         },                                                             \
4003         {                                                              \
4004             .fniv = gen_## NAME ##_u_vec,                              \
4005             .fnoi = gen_helper_## NAME ##_wu,                          \
4006             .opt_opc = vecop_list,                                     \
4007             .vece = MO_32                                              \
4008         },                                                             \
4009         {                                                              \
4010             .fniv = gen_## NAME ##_u_vec,                              \
4011             .fnoi = gen_helper_## NAME ##_du,                          \
4012             .opt_opc = vecop_list,                                     \
4013             .vece = MO_64                                              \
4014         }                                                              \
4015     };                                                                 \
4016                                                                        \
4017     vd_ofs = vec_full_offset(a->vd);                                   \
4018     vj_ofs = vec_full_offset(a->vj);                                   \
4019                                                                        \
4020     tcg_gen_gvec_2i(vd_ofs, vj_ofs, 16, ctx->vl/8, a->imm, &op[mop]);  \
4021                                                                        \
4022     return true;                                                       \
4025 DO_CMPI_U(vslei)
4026 DO_CMPI_U(vslti)
4028 TRANS(vseq_b, LSX, do_cmp, MO_8, TCG_COND_EQ)
4029 TRANS(vseq_h, LSX, do_cmp, MO_16, TCG_COND_EQ)
4030 TRANS(vseq_w, LSX, do_cmp, MO_32, TCG_COND_EQ)
4031 TRANS(vseq_d, LSX, do_cmp, MO_64, TCG_COND_EQ)
4032 TRANS(vseqi_b, LSX, do_vseqi_s, MO_8)
4033 TRANS(vseqi_h, LSX, do_vseqi_s, MO_16)
4034 TRANS(vseqi_w, LSX, do_vseqi_s, MO_32)
4035 TRANS(vseqi_d, LSX, do_vseqi_s, MO_64)
4037 TRANS(vsle_b, LSX, do_cmp, MO_8, TCG_COND_LE)
4038 TRANS(vsle_h, LSX, do_cmp, MO_16, TCG_COND_LE)
4039 TRANS(vsle_w, LSX, do_cmp, MO_32, TCG_COND_LE)
4040 TRANS(vsle_d, LSX, do_cmp, MO_64, TCG_COND_LE)
4041 TRANS(vslei_b, LSX, do_vslei_s, MO_8)
4042 TRANS(vslei_h, LSX, do_vslei_s, MO_16)
4043 TRANS(vslei_w, LSX, do_vslei_s, MO_32)
4044 TRANS(vslei_d, LSX, do_vslei_s, MO_64)
4045 TRANS(vsle_bu, LSX, do_cmp, MO_8, TCG_COND_LEU)
4046 TRANS(vsle_hu, LSX, do_cmp, MO_16, TCG_COND_LEU)
4047 TRANS(vsle_wu, LSX, do_cmp, MO_32, TCG_COND_LEU)
4048 TRANS(vsle_du, LSX, do_cmp, MO_64, TCG_COND_LEU)
4049 TRANS(vslei_bu, LSX, do_vslei_u, MO_8)
4050 TRANS(vslei_hu, LSX, do_vslei_u, MO_16)
4051 TRANS(vslei_wu, LSX, do_vslei_u, MO_32)
4052 TRANS(vslei_du, LSX, do_vslei_u, MO_64)
4054 TRANS(vslt_b, LSX, do_cmp, MO_8, TCG_COND_LT)
4055 TRANS(vslt_h, LSX, do_cmp, MO_16, TCG_COND_LT)
4056 TRANS(vslt_w, LSX, do_cmp, MO_32, TCG_COND_LT)
4057 TRANS(vslt_d, LSX, do_cmp, MO_64, TCG_COND_LT)
4058 TRANS(vslti_b, LSX, do_vslti_s, MO_8)
4059 TRANS(vslti_h, LSX, do_vslti_s, MO_16)
4060 TRANS(vslti_w, LSX, do_vslti_s, MO_32)
4061 TRANS(vslti_d, LSX, do_vslti_s, MO_64)
4062 TRANS(vslt_bu, LSX, do_cmp, MO_8, TCG_COND_LTU)
4063 TRANS(vslt_hu, LSX, do_cmp, MO_16, TCG_COND_LTU)
4064 TRANS(vslt_wu, LSX, do_cmp, MO_32, TCG_COND_LTU)
4065 TRANS(vslt_du, LSX, do_cmp, MO_64, TCG_COND_LTU)
4066 TRANS(vslti_bu, LSX, do_vslti_u, MO_8)
4067 TRANS(vslti_hu, LSX, do_vslti_u, MO_16)
4068 TRANS(vslti_wu, LSX, do_vslti_u, MO_32)
4069 TRANS(vslti_du, LSX, do_vslti_u, MO_64)
4071 static bool trans_vfcmp_cond_s(DisasContext *ctx, arg_vvv_fcond *a)
4073     uint32_t flags;
4074     void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
4075     TCGv_i32 vd = tcg_constant_i32(a->vd);
4076     TCGv_i32 vj = tcg_constant_i32(a->vj);
4077     TCGv_i32 vk = tcg_constant_i32(a->vk);
4079     if (!avail_LSX(ctx)) {
4080         return false;
4081     }
4083     if (!check_vec(ctx, 16)) {
4084         return true;
4085     }
4087     fn = (a->fcond & 1 ? gen_helper_vfcmp_s_s : gen_helper_vfcmp_c_s);
4088     flags = get_fcmp_flags(a->fcond >> 1);
4089     fn(cpu_env, vd, vj, vk,  tcg_constant_i32(flags));
4091     return true;
4094 static bool trans_vfcmp_cond_d(DisasContext *ctx, arg_vvv_fcond *a)
4096     uint32_t flags;
4097     void (*fn)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
4098     TCGv_i32 vd = tcg_constant_i32(a->vd);
4099     TCGv_i32 vj = tcg_constant_i32(a->vj);
4100     TCGv_i32 vk = tcg_constant_i32(a->vk);
4102     if (!avail_LSX(ctx)) {
4103         return false;
4104     }
4106     if (!check_vec(ctx, 16)) {
4107         return true;
4108     }
4110     fn = (a->fcond & 1 ? gen_helper_vfcmp_s_d : gen_helper_vfcmp_c_d);
4111     flags = get_fcmp_flags(a->fcond >> 1);
4112     fn(cpu_env, vd, vj, vk, tcg_constant_i32(flags));
4114     return true;
4117 static bool trans_vbitsel_v(DisasContext *ctx, arg_vvvv *a)
4119     if (!avail_LSX(ctx)) {
4120         return false;
4121     }
4123     if (!check_vec(ctx, 16)) {
4124         return true;
4125     }
4127     tcg_gen_gvec_bitsel(MO_64, vec_full_offset(a->vd), vec_full_offset(a->va),
4128                         vec_full_offset(a->vk), vec_full_offset(a->vj),
4129                         16, ctx->vl/8);
4130     return true;
4133 static void gen_vbitseli(unsigned vece, TCGv_vec a, TCGv_vec b, int64_t imm)
4135     tcg_gen_bitsel_vec(vece, a, a, tcg_constant_vec_matching(a, vece, imm), b);
4138 static bool trans_vbitseli_b(DisasContext *ctx, arg_vv_i *a)
4140     static const GVecGen2i op = {
4141        .fniv = gen_vbitseli,
4142        .fnoi = gen_helper_vbitseli_b,
4143        .vece = MO_8,
4144        .load_dest = true
4145     };
4147     if (!avail_LSX(ctx)) {
4148         return false;
4149     }
4151     if (!check_vec(ctx, 16)) {
4152         return true;
4153     }
4155     tcg_gen_gvec_2i(vec_full_offset(a->vd), vec_full_offset(a->vj),
4156                     16, ctx->vl/8, a->imm, &op);
4157     return true;
4160 #define VSET(NAME, COND)                                                       \
4161 static bool trans_## NAME (DisasContext *ctx, arg_cv *a)                       \
4162 {                                                                              \
4163     TCGv_i64 t1, al, ah;                                                       \
4164                                                                                \
4165     al = tcg_temp_new_i64();                                                   \
4166     ah = tcg_temp_new_i64();                                                   \
4167     t1 = tcg_temp_new_i64();                                                   \
4168                                                                                \
4169     get_vreg64(ah, a->vj, 1);                                                  \
4170     get_vreg64(al, a->vj, 0);                                                  \
4171                                                                                \
4172     if (!avail_LSX(ctx)) {                                                     \
4173         return false;                                                          \
4174     }                                                                          \
4175                                                                                \
4176     if (!check_vec(ctx, 16)) {                                                 \
4177         return true;                                                           \
4178     }                                                                          \
4179                                                                                \
4180     tcg_gen_or_i64(t1, al, ah);                                                \
4181     tcg_gen_setcondi_i64(COND, t1, t1, 0);                                     \
4182     tcg_gen_st8_tl(t1, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); \
4183                                                                                \
4184     return true;                                                               \
4187 VSET(vseteqz_v, TCG_COND_EQ)
4188 VSET(vsetnez_v, TCG_COND_NE)
4190 TRANS(vsetanyeqz_b, LSX, gen_cv, gen_helper_vsetanyeqz_b)
4191 TRANS(vsetanyeqz_h, LSX, gen_cv, gen_helper_vsetanyeqz_h)
4192 TRANS(vsetanyeqz_w, LSX, gen_cv, gen_helper_vsetanyeqz_w)
4193 TRANS(vsetanyeqz_d, LSX, gen_cv, gen_helper_vsetanyeqz_d)
4194 TRANS(vsetallnez_b, LSX, gen_cv, gen_helper_vsetallnez_b)
4195 TRANS(vsetallnez_h, LSX, gen_cv, gen_helper_vsetallnez_h)
4196 TRANS(vsetallnez_w, LSX, gen_cv, gen_helper_vsetallnez_w)
4197 TRANS(vsetallnez_d, LSX, gen_cv, gen_helper_vsetallnez_d)
4199 static bool trans_vinsgr2vr_b(DisasContext *ctx, arg_vr_i *a)
4201     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
4203     if (!avail_LSX(ctx)) {
4204         return false;
4205     }
4207     if (!check_vec(ctx, 16)) {
4208         return true;
4209     }
4211     tcg_gen_st8_i64(src, cpu_env,
4212                     offsetof(CPULoongArchState, fpr[a->vd].vreg.B(a->imm)));
4213     return true;
4216 static bool trans_vinsgr2vr_h(DisasContext *ctx, arg_vr_i *a)
4218     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
4220     if (!avail_LSX(ctx)) {
4221         return false;
4222     }
4224     if (!check_vec(ctx, 16)) {
4225         return true;
4226     }
4228     tcg_gen_st16_i64(src, cpu_env,
4229                     offsetof(CPULoongArchState, fpr[a->vd].vreg.H(a->imm)));
4230     return true;
4233 static bool trans_vinsgr2vr_w(DisasContext *ctx, arg_vr_i *a)
4235     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
4237     if (!avail_LSX(ctx)) {
4238         return false;
4239     }
4241     if (!check_vec(ctx, 16)) {
4242         return true;
4243     }
4245     tcg_gen_st32_i64(src, cpu_env,
4246                      offsetof(CPULoongArchState, fpr[a->vd].vreg.W(a->imm)));
4247     return true;
4250 static bool trans_vinsgr2vr_d(DisasContext *ctx, arg_vr_i *a)
4252     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
4254     if (!avail_LSX(ctx)) {
4255         return false;
4256     }
4258     if (!check_vec(ctx, 16)) {
4259         return true;
4260     }
4262     tcg_gen_st_i64(src, cpu_env,
4263                    offsetof(CPULoongArchState, fpr[a->vd].vreg.D(a->imm)));
4264     return true;
4267 static bool trans_vpickve2gr_b(DisasContext *ctx, arg_rv_i *a)
4269     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4271     if (!avail_LSX(ctx)) {
4272         return false;
4273     }
4275     if (!check_vec(ctx, 16)) {
4276         return true;
4277     }
4279     tcg_gen_ld8s_i64(dst, cpu_env,
4280                      offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
4281     return true;
4284 static bool trans_vpickve2gr_h(DisasContext *ctx, arg_rv_i *a)
4286     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4288     if (!avail_LSX(ctx)) {
4289         return false;
4290     }
4292     if (!check_vec(ctx, 16)) {
4293         return true;
4294     }
4296     tcg_gen_ld16s_i64(dst, cpu_env,
4297                       offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
4298     return true;
4301 static bool trans_vpickve2gr_w(DisasContext *ctx, arg_rv_i *a)
4303     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4305     if (!avail_LSX(ctx)) {
4306         return false;
4307     }
4309     if (!check_vec(ctx, 16)) {
4310         return true;
4311     }
4313     tcg_gen_ld32s_i64(dst, cpu_env,
4314                       offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm)));
4315     return true;
4318 static bool trans_vpickve2gr_d(DisasContext *ctx, arg_rv_i *a)
4320     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4322     if (!avail_LSX(ctx)) {
4323         return false;
4324     }
4326     if (!check_vec(ctx, 16)) {
4327         return true;
4328     }
4330     tcg_gen_ld_i64(dst, cpu_env,
4331                    offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm)));
4332     return true;
4335 static bool trans_vpickve2gr_bu(DisasContext *ctx, arg_rv_i *a)
4337     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4339     if (!avail_LSX(ctx)) {
4340         return false;
4341     }
4343     if (!check_vec(ctx, 16)) {
4344         return true;
4345     }
4347     tcg_gen_ld8u_i64(dst, cpu_env,
4348                      offsetof(CPULoongArchState, fpr[a->vj].vreg.B(a->imm)));
4349     return true;
4352 static bool trans_vpickve2gr_hu(DisasContext *ctx, arg_rv_i *a)
4354     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4356     if (!avail_LSX(ctx)) {
4357         return false;
4358     }
4360     if (!check_vec(ctx, 16)) {
4361         return true;
4362     }
4364     tcg_gen_ld16u_i64(dst, cpu_env,
4365                       offsetof(CPULoongArchState, fpr[a->vj].vreg.H(a->imm)));
4366     return true;
4369 static bool trans_vpickve2gr_wu(DisasContext *ctx, arg_rv_i *a)
4371     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4373     if (!avail_LSX(ctx)) {
4374         return false;
4375     }
4377     if (!check_vec(ctx, 16)) {
4378         return true;
4379     }
4381     tcg_gen_ld32u_i64(dst, cpu_env,
4382                       offsetof(CPULoongArchState, fpr[a->vj].vreg.W(a->imm)));
4383     return true;
4386 static bool trans_vpickve2gr_du(DisasContext *ctx, arg_rv_i *a)
4388     TCGv dst = gpr_dst(ctx, a->rd, EXT_NONE);
4390     if (!avail_LSX(ctx)) {
4391         return false;
4392     }
4394     if (!check_vec(ctx, 16)) {
4395         return true;
4396     }
4398     tcg_gen_ld_i64(dst, cpu_env,
4399                    offsetof(CPULoongArchState, fpr[a->vj].vreg.D(a->imm)));
4400     return true;
4403 static bool gvec_dup(DisasContext *ctx, arg_vr *a, MemOp mop)
4405     TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
4407     if (!avail_LSX(ctx)) {
4408         return false;
4409     }
4411     if (!check_vec(ctx, 16)) {
4412         return true;
4413     }
4415     tcg_gen_gvec_dup_i64(mop, vec_full_offset(a->vd),
4416                          16, ctx->vl/8, src);
4417     return true;
4420 TRANS(vreplgr2vr_b, LSX, gvec_dup, MO_8)
4421 TRANS(vreplgr2vr_h, LSX, gvec_dup, MO_16)
4422 TRANS(vreplgr2vr_w, LSX, gvec_dup, MO_32)
4423 TRANS(vreplgr2vr_d, LSX, gvec_dup, MO_64)
4425 static bool trans_vreplvei_b(DisasContext *ctx, arg_vv_i *a)
4427     if (!avail_LSX(ctx)) {
4428         return false;
4429     }
4431     if (!check_vec(ctx, 16)) {
4432         return true;
4433     }
4435     tcg_gen_gvec_dup_mem(MO_8,vec_full_offset(a->vd),
4436                          offsetof(CPULoongArchState,
4437                                   fpr[a->vj].vreg.B((a->imm))),
4438                          16, ctx->vl/8);
4439     return true;
4442 static bool trans_vreplvei_h(DisasContext *ctx, arg_vv_i *a)
4444     if (!avail_LSX(ctx)) {
4445         return false;
4446     }
4448     if (!check_vec(ctx, 16)) {
4449         return true;
4450     }
4452     tcg_gen_gvec_dup_mem(MO_16, vec_full_offset(a->vd),
4453                          offsetof(CPULoongArchState,
4454                                   fpr[a->vj].vreg.H((a->imm))),
4455                          16, ctx->vl/8);
4456     return true;
4458 static bool trans_vreplvei_w(DisasContext *ctx, arg_vv_i *a)
4460     if (!avail_LSX(ctx)) {
4461         return false;
4462     }
4464     if (!check_vec(ctx, 16)) {
4465         return true;
4466     }
4468     tcg_gen_gvec_dup_mem(MO_32, vec_full_offset(a->vd),
4469                          offsetof(CPULoongArchState,
4470                                   fpr[a->vj].vreg.W((a->imm))),
4471                         16, ctx->vl/8);
4472     return true;
4474 static bool trans_vreplvei_d(DisasContext *ctx, arg_vv_i *a)
4476     if (!avail_LSX(ctx)) {
4477         return false;
4478     }
4480     if (!check_vec(ctx, 16)) {
4481         return true;
4482     }
4484     tcg_gen_gvec_dup_mem(MO_64, vec_full_offset(a->vd),
4485                          offsetof(CPULoongArchState,
4486                                   fpr[a->vj].vreg.D((a->imm))),
4487                          16, ctx->vl/8);
4488     return true;
4491 static bool gen_vreplve(DisasContext *ctx, arg_vvr *a, int vece, int bit,
4492                         void (*func)(TCGv_i64, TCGv_ptr, tcg_target_long))
4494     TCGv_i64 t0 = tcg_temp_new_i64();
4495     TCGv_ptr t1 = tcg_temp_new_ptr();
4496     TCGv_i64 t2 = tcg_temp_new_i64();
4498     if (!avail_LSX(ctx)) {
4499         return false;
4500     }
4502     if (!check_vec(ctx, 16)) {
4503         return true;
4504     }
4506     tcg_gen_andi_i64(t0, gpr_src(ctx, a->rk, EXT_NONE), (LSX_LEN/bit) -1);
4507     tcg_gen_shli_i64(t0, t0, vece);
4508     if (HOST_BIG_ENDIAN) {
4509         tcg_gen_xori_i64(t0, t0, vece << ((LSX_LEN/bit) -1));
4510     }
4512     tcg_gen_trunc_i64_ptr(t1, t0);
4513     tcg_gen_add_ptr(t1, t1, cpu_env);
4514     func(t2, t1, vec_full_offset(a->vj));
4515     tcg_gen_gvec_dup_i64(vece, vec_full_offset(a->vd), 16, ctx->vl/8, t2);
4517     return true;
4520 TRANS(vreplve_b, LSX, gen_vreplve, MO_8,  8, tcg_gen_ld8u_i64)
4521 TRANS(vreplve_h, LSX, gen_vreplve, MO_16, 16, tcg_gen_ld16u_i64)
4522 TRANS(vreplve_w, LSX, gen_vreplve, MO_32, 32, tcg_gen_ld32u_i64)
4523 TRANS(vreplve_d, LSX, gen_vreplve, MO_64, 64, tcg_gen_ld_i64)
4525 static bool trans_vbsll_v(DisasContext *ctx, arg_vv_i *a)
4527     int ofs;
4528     TCGv_i64 desthigh, destlow, high, low;
4530     if (!avail_LSX(ctx)) {
4531         return false;
4532     }
4534     if (!check_vec(ctx, 16)) {
4535         return true;
4536     }
4538     desthigh = tcg_temp_new_i64();
4539     destlow = tcg_temp_new_i64();
4540     high = tcg_temp_new_i64();
4541     low = tcg_temp_new_i64();
4543     get_vreg64(low, a->vj, 0);
4545     ofs = ((a->imm) & 0xf) * 8;
4546     if (ofs < 64) {
4547         get_vreg64(high, a->vj, 1);
4548         tcg_gen_extract2_i64(desthigh, low, high, 64 - ofs);
4549         tcg_gen_shli_i64(destlow, low, ofs);
4550     } else {
4551         tcg_gen_shli_i64(desthigh, low, ofs - 64);
4552         destlow = tcg_constant_i64(0);
4553     }
4555     set_vreg64(desthigh, a->vd, 1);
4556     set_vreg64(destlow, a->vd, 0);
4558     return true;
4561 static bool trans_vbsrl_v(DisasContext *ctx, arg_vv_i *a)
4563     TCGv_i64 desthigh, destlow, high, low;
4564     int ofs;
4566     if (!avail_LSX(ctx)) {
4567         return false;
4568     }
4570     if (!check_vec(ctx, 16)) {
4571         return true;
4572     }
4574     desthigh = tcg_temp_new_i64();
4575     destlow = tcg_temp_new_i64();
4576     high = tcg_temp_new_i64();
4577     low = tcg_temp_new_i64();
4579     get_vreg64(high, a->vj, 1);
4581     ofs = ((a->imm) & 0xf) * 8;
4582     if (ofs < 64) {
4583         get_vreg64(low, a->vj, 0);
4584         tcg_gen_extract2_i64(destlow, low, high, ofs);
4585         tcg_gen_shri_i64(desthigh, high, ofs);
4586     } else {
4587         tcg_gen_shri_i64(destlow, high, ofs - 64);
4588         desthigh = tcg_constant_i64(0);
4589     }
4591     set_vreg64(desthigh, a->vd, 1);
4592     set_vreg64(destlow, a->vd, 0);
4594     return true;
4597 TRANS(vpackev_b, LSX, gen_vvv, gen_helper_vpackev_b)
4598 TRANS(vpackev_h, LSX, gen_vvv, gen_helper_vpackev_h)
4599 TRANS(vpackev_w, LSX, gen_vvv, gen_helper_vpackev_w)
4600 TRANS(vpackev_d, LSX, gen_vvv, gen_helper_vpackev_d)
4601 TRANS(vpackod_b, LSX, gen_vvv, gen_helper_vpackod_b)
4602 TRANS(vpackod_h, LSX, gen_vvv, gen_helper_vpackod_h)
4603 TRANS(vpackod_w, LSX, gen_vvv, gen_helper_vpackod_w)
4604 TRANS(vpackod_d, LSX, gen_vvv, gen_helper_vpackod_d)
4606 TRANS(vpickev_b, LSX, gen_vvv, gen_helper_vpickev_b)
4607 TRANS(vpickev_h, LSX, gen_vvv, gen_helper_vpickev_h)
4608 TRANS(vpickev_w, LSX, gen_vvv, gen_helper_vpickev_w)
4609 TRANS(vpickev_d, LSX, gen_vvv, gen_helper_vpickev_d)
4610 TRANS(vpickod_b, LSX, gen_vvv, gen_helper_vpickod_b)
4611 TRANS(vpickod_h, LSX, gen_vvv, gen_helper_vpickod_h)
4612 TRANS(vpickod_w, LSX, gen_vvv, gen_helper_vpickod_w)
4613 TRANS(vpickod_d, LSX, gen_vvv, gen_helper_vpickod_d)
4615 TRANS(vilvl_b, LSX, gen_vvv, gen_helper_vilvl_b)
4616 TRANS(vilvl_h, LSX, gen_vvv, gen_helper_vilvl_h)
4617 TRANS(vilvl_w, LSX, gen_vvv, gen_helper_vilvl_w)
4618 TRANS(vilvl_d, LSX, gen_vvv, gen_helper_vilvl_d)
4619 TRANS(vilvh_b, LSX, gen_vvv, gen_helper_vilvh_b)
4620 TRANS(vilvh_h, LSX, gen_vvv, gen_helper_vilvh_h)
4621 TRANS(vilvh_w, LSX, gen_vvv, gen_helper_vilvh_w)
4622 TRANS(vilvh_d, LSX, gen_vvv, gen_helper_vilvh_d)
4624 TRANS(vshuf_b, LSX, gen_vvvv, gen_helper_vshuf_b)
4625 TRANS(vshuf_h, LSX, gen_vvv, gen_helper_vshuf_h)
4626 TRANS(vshuf_w, LSX, gen_vvv, gen_helper_vshuf_w)
4627 TRANS(vshuf_d, LSX, gen_vvv, gen_helper_vshuf_d)
4628 TRANS(vshuf4i_b, LSX, gen_vv_i, gen_helper_vshuf4i_b)
4629 TRANS(vshuf4i_h, LSX, gen_vv_i, gen_helper_vshuf4i_h)
4630 TRANS(vshuf4i_w, LSX, gen_vv_i, gen_helper_vshuf4i_w)
4631 TRANS(vshuf4i_d, LSX, gen_vv_i, gen_helper_vshuf4i_d)
4633 TRANS(vpermi_w, LSX, gen_vv_i, gen_helper_vpermi_w)
4635 TRANS(vextrins_b, LSX, gen_vv_i, gen_helper_vextrins_b)
4636 TRANS(vextrins_h, LSX, gen_vv_i, gen_helper_vextrins_h)
4637 TRANS(vextrins_w, LSX, gen_vv_i, gen_helper_vextrins_w)
4638 TRANS(vextrins_d, LSX, gen_vv_i, gen_helper_vextrins_d)
4640 static bool trans_vld(DisasContext *ctx, arg_vr_i *a)
4642     TCGv addr;
4643     TCGv_i64 rl, rh;
4644     TCGv_i128 val;
4646     if (!avail_LSX(ctx)) {
4647         return false;
4648     }
4650     if (!check_vec(ctx, 16)) {
4651         return true;
4652     }
4654     addr = gpr_src(ctx, a->rj, EXT_NONE);
4655     val = tcg_temp_new_i128();
4656     rl = tcg_temp_new_i64();
4657     rh = tcg_temp_new_i64();
4659     addr = make_address_i(ctx, addr, a->imm);
4661     tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
4662     tcg_gen_extr_i128_i64(rl, rh, val);
4663     set_vreg64(rh, a->vd, 1);
4664     set_vreg64(rl, a->vd, 0);
4666     return true;
4669 static bool trans_vst(DisasContext *ctx, arg_vr_i *a)
4671     TCGv addr;
4672     TCGv_i128 val;
4673     TCGv_i64 ah, al;
4675     if (!avail_LSX(ctx)) {
4676         return false;
4677     }
4679     if (!check_vec(ctx, 16)) {
4680         return true;
4681     }
4683     addr = gpr_src(ctx, a->rj, EXT_NONE);
4684     val = tcg_temp_new_i128();
4685     ah = tcg_temp_new_i64();
4686     al = tcg_temp_new_i64();
4688     addr = make_address_i(ctx, addr, a->imm);
4690     get_vreg64(ah, a->vd, 1);
4691     get_vreg64(al, a->vd, 0);
4692     tcg_gen_concat_i64_i128(val, al, ah);
4693     tcg_gen_qemu_st_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
4695     return true;
4698 static bool trans_vldx(DisasContext *ctx, arg_vrr *a)
4700     TCGv addr, src1, src2;
4701     TCGv_i64 rl, rh;
4702     TCGv_i128 val;
4704     if (!avail_LSX(ctx)) {
4705         return false;
4706     }
4708     if (!check_vec(ctx, 16)) {
4709         return true;
4710     }
4712     src1 = gpr_src(ctx, a->rj, EXT_NONE);
4713     src2 = gpr_src(ctx, a->rk, EXT_NONE);
4714     val = tcg_temp_new_i128();
4715     rl = tcg_temp_new_i64();
4716     rh = tcg_temp_new_i64();
4718     addr = make_address_x(ctx, src1, src2);
4719     tcg_gen_qemu_ld_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
4720     tcg_gen_extr_i128_i64(rl, rh, val);
4721     set_vreg64(rh, a->vd, 1);
4722     set_vreg64(rl, a->vd, 0);
4724     return true;
4727 static bool trans_vstx(DisasContext *ctx, arg_vrr *a)
4729     TCGv addr, src1, src2;
4730     TCGv_i64 ah, al;
4731     TCGv_i128 val;
4733     if (!avail_LSX(ctx)) {
4734         return false;
4735     }
4737     if (!check_vec(ctx, 16)) {
4738         return true;
4739     }
4741     src1 = gpr_src(ctx, a->rj, EXT_NONE);
4742     src2 = gpr_src(ctx, a->rk, EXT_NONE);
4743     val = tcg_temp_new_i128();
4744     ah = tcg_temp_new_i64();
4745     al = tcg_temp_new_i64();
4747     addr = make_address_x(ctx, src1, src2);
4748     get_vreg64(ah, a->vd, 1);
4749     get_vreg64(al, a->vd, 0);
4750     tcg_gen_concat_i64_i128(val, al, ah);
4751     tcg_gen_qemu_st_i128(val, addr, ctx->mem_idx, MO_128 | MO_TE);
4753     return true;
4756 #define VLDREPL(NAME, MO)                                                 \
4757 static bool trans_## NAME (DisasContext *ctx, arg_vr_i *a)                \
4758 {                                                                         \
4759     TCGv addr;                                                            \
4760     TCGv_i64 val;                                                         \
4761                                                                           \
4762     if (!avail_LSX(ctx)) {                                                \
4763         return false;                                                     \
4764     }                                                                     \
4765                                                                           \
4766     if (!check_vec(ctx, 16)) {                                            \
4767         return true;                                                      \
4768     }                                                                     \
4769                                                                           \
4770     addr = gpr_src(ctx, a->rj, EXT_NONE);                                 \
4771     val = tcg_temp_new_i64();                                             \
4772                                                                           \
4773     addr = make_address_i(ctx, addr, a->imm);                             \
4774                                                                           \
4775     tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, MO);                     \
4776     tcg_gen_gvec_dup_i64(MO, vec_full_offset(a->vd), 16, ctx->vl/8, val); \
4777                                                                           \
4778     return true;                                                          \
4781 VLDREPL(vldrepl_b, MO_8)
4782 VLDREPL(vldrepl_h, MO_16)
4783 VLDREPL(vldrepl_w, MO_32)
4784 VLDREPL(vldrepl_d, MO_64)
4786 #define VSTELM(NAME, MO, E)                                                  \
4787 static bool trans_## NAME (DisasContext *ctx, arg_vr_ii *a)                  \
4788 {                                                                            \
4789     TCGv addr;                                                               \
4790     TCGv_i64 val;                                                            \
4791                                                                              \
4792     if (!avail_LSX(ctx)) {                                                   \
4793         return false;                                                        \
4794     }                                                                        \
4795                                                                              \
4796     if (!check_vec(ctx, 16)) {                                               \
4797         return true;                                                         \
4798     }                                                                        \
4799                                                                              \
4800     addr = gpr_src(ctx, a->rj, EXT_NONE);                                    \
4801     val = tcg_temp_new_i64();                                                \
4802                                                                              \
4803     addr = make_address_i(ctx, addr, a->imm);                                \
4804                                                                              \
4805     tcg_gen_ld_i64(val, cpu_env,                                             \
4806                    offsetof(CPULoongArchState, fpr[a->vd].vreg.E(a->imm2))); \
4807     tcg_gen_qemu_st_i64(val, addr, ctx->mem_idx, MO);                        \
4808                                                                              \
4809     return true;                                                             \
4812 VSTELM(vstelm_b, MO_8, B)
4813 VSTELM(vstelm_h, MO_16, H)
4814 VSTELM(vstelm_w, MO_32, W)
4815 VSTELM(vstelm_d, MO_64, D)