xref: /openbmc/qemu/target/mips/tcg/msa_translate.c (revision 0a510c93)
1 /*
2  *  MIPS SIMD Architecture (MSA) translation routines
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *  Copyright (c) 2006 Marius Groeger (FPU operations)
6  *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7  *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8  *  Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9  *  Copyright (c) 2020 Philippe Mathieu-Daudé
10  *
11  * SPDX-License-Identifier: LGPL-2.1-or-later
12  */
13 #include "qemu/osdep.h"
14 #include "tcg/tcg-op.h"
15 #include "exec/helper-gen.h"
16 #include "translate.h"
17 #include "fpu_helper.h"
18 #include "internal.h"
19 
20 static int elm_n(DisasContext *ctx, int x);
21 static int elm_df(DisasContext *ctx, int x);
22 static int bit_m(DisasContext *ctx, int x);
23 static int bit_df(DisasContext *ctx, int x);
24 
25 static inline int plus_1(DisasContext *s, int x)
26 {
27     return x + 1;
28 }
29 
30 static inline int plus_2(DisasContext *s, int x)
31 {
32     return x + 2;
33 }
34 
35 /* Include the auto-generated decoder.  */
36 #include "decode-msa.c.inc"
37 
38 #define OPC_MSA (0x1E << 26)
39 
40 #define MASK_MSA_MINOR(op)          (MASK_OP_MAJOR(op) | (op & 0x3F))
41 enum {
42     OPC_MSA_ELM     = 0x19 | OPC_MSA,
43 };
44 
45 enum {
46     /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
47     OPC_CTCMSA      = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
48     OPC_CFCMSA      = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
49     OPC_COPY_S_df   = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
50     OPC_MOVE_V      = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
51     OPC_COPY_U_df   = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
52     OPC_INSERT_df   = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
53 };
54 
55 static const char msaregnames[][6] = {
56     "w0.d0",  "w0.d1",  "w1.d0",  "w1.d1",
57     "w2.d0",  "w2.d1",  "w3.d0",  "w3.d1",
58     "w4.d0",  "w4.d1",  "w5.d0",  "w5.d1",
59     "w6.d0",  "w6.d1",  "w7.d0",  "w7.d1",
60     "w8.d0",  "w8.d1",  "w9.d0",  "w9.d1",
61     "w10.d0", "w10.d1", "w11.d0", "w11.d1",
62     "w12.d0", "w12.d1", "w13.d0", "w13.d1",
63     "w14.d0", "w14.d1", "w15.d0", "w15.d1",
64     "w16.d0", "w16.d1", "w17.d0", "w17.d1",
65     "w18.d0", "w18.d1", "w19.d0", "w19.d1",
66     "w20.d0", "w20.d1", "w21.d0", "w21.d1",
67     "w22.d0", "w22.d1", "w23.d0", "w23.d1",
68     "w24.d0", "w24.d1", "w25.d0", "w25.d1",
69     "w26.d0", "w26.d1", "w27.d0", "w27.d1",
70     "w28.d0", "w28.d1", "w29.d0", "w29.d1",
71     "w30.d0", "w30.d1", "w31.d0", "w31.d1",
72 };
73 
74 /* Encoding of Operation Field (must be indexed by CPUMIPSMSADataFormat) */
75 struct dfe {
76     int start;
77     int length;
78     uint32_t mask;
79 };
80 
81 /*
82  * Extract immediate from df/{m,n} format (used by ELM & BIT instructions).
83  * Returns the immediate value, or -1 if the format does not match.
84  */
85 static int df_extract_val(DisasContext *ctx, int x, const struct dfe *s)
86 {
87     for (unsigned i = 0; i < 4; i++) {
88         if (extract32(x, s->start, s->length) == s->mask) {
89             return extract32(x, 0, s->start);
90         }
91     }
92     return -1;
93 }
94 
95 /*
96  * Extract DataField from df/{m,n} format (used by ELM & BIT instructions).
97  * Returns the DataField, or -1 if the format does not match.
98  */
99 static int df_extract_df(DisasContext *ctx, int x, const struct dfe *s)
100 {
101     for (unsigned i = 0; i < 4; i++) {
102         if (extract32(x, s->start, s->length) == s->mask) {
103             return i;
104         }
105     }
106     return -1;
107 }
108 
109 static const struct dfe df_elm[] = {
110     /* Table 3.26 ELM Instruction Format */
111     [DF_BYTE]   = {4, 2, 0b00},
112     [DF_HALF]   = {3, 3, 0b100},
113     [DF_WORD]   = {2, 4, 0b1100},
114     [DF_DOUBLE] = {1, 5, 0b11100}
115 };
116 
117 static int elm_n(DisasContext *ctx, int x)
118 {
119     return df_extract_val(ctx, x, df_elm);
120 }
121 
122 static int elm_df(DisasContext *ctx, int x)
123 {
124     return df_extract_df(ctx, x, df_elm);
125 }
126 
127 static const struct dfe df_bit[] = {
128     /* Table 3.28 BIT Instruction Format */
129     [DF_BYTE]   = {3, 4, 0b1110},
130     [DF_HALF]   = {4, 3, 0b110},
131     [DF_WORD]   = {5, 2, 0b10},
132     [DF_DOUBLE] = {6, 1, 0b0}
133 };
134 
135 static int bit_m(DisasContext *ctx, int x)
136 {
137     return df_extract_val(ctx, x, df_bit);
138 }
139 
140 static int bit_df(DisasContext *ctx, int x)
141 {
142     return df_extract_df(ctx, x, df_bit);
143 }
144 
145 static TCGv_i64 msa_wr_d[64];
146 
147 void msa_translate_init(void)
148 {
149     int i;
150 
151     for (i = 0; i < 32; i++) {
152         int off;
153 
154         /*
155          * The MSA vector registers are mapped on the
156          * scalar floating-point unit (FPU) registers.
157          */
158         off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
159         msa_wr_d[i * 2] = fpu_f64[i];
160 
161         off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
162         msa_wr_d[i * 2 + 1] =
163                 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
164     }
165 }
166 
167 /*
168  * Check if MSA is enabled.
169  * This function is always called with MSA available.
170  * If MSA is disabled, raise an exception.
171  */
172 static inline bool check_msa_enabled(DisasContext *ctx)
173 {
174     if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
175                  !(ctx->hflags & MIPS_HFLAG_F64))) {
176         gen_reserved_instruction(ctx);
177         return false;
178     }
179 
180     if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
181         generate_exception_end(ctx, EXCP_MSADIS);
182         return false;
183     }
184     return true;
185 }
186 
187 typedef void gen_helper_piv(TCGv_ptr, TCGv_i32, TCGv);
188 typedef void gen_helper_pii(TCGv_ptr, TCGv_i32, TCGv_i32);
189 typedef void gen_helper_piii(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
190 typedef void gen_helper_piiii(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32);
191 
192 #define TRANS_DF_x(TYPE, NAME, trans_func, gen_func) \
193     static gen_helper_p##TYPE * const NAME##_tab[4] = { \
194         gen_func##_b, gen_func##_h, gen_func##_w, gen_func##_d \
195     }; \
196     TRANS(NAME, trans_func, NAME##_tab[a->df])
197 
198 #define TRANS_DF_iv(NAME, trans_func, gen_func) \
199     TRANS_DF_x(iv, NAME, trans_func, gen_func)
200 
201 #define TRANS_DF_ii(NAME, trans_func, gen_func) \
202     TRANS_DF_x(ii, NAME, trans_func, gen_func)
203 
204 #define TRANS_DF_iii(NAME, trans_func, gen_func) \
205     TRANS_DF_x(iii, NAME, trans_func, gen_func)
206 
207 #define TRANS_DF_iii_b(NAME, trans_func, gen_func) \
208     static gen_helper_piii * const NAME##_tab[4] = { \
209         NULL, gen_func##_h, gen_func##_w, gen_func##_d \
210     }; \
211     static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
212     { \
213         return trans_func(ctx, a, NAME##_tab[a->df]); \
214     }
215 
216 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt,
217                                    TCGCond cond)
218 {
219     /* generates tcg ops to check if any element is 0 */
220     /* Note this function only works with MSA_WRLEN = 128 */
221     uint64_t eval_zero_or_big = dup_const(df, 1);
222     uint64_t eval_big = eval_zero_or_big << ((8 << df) - 1);
223     TCGv_i64 t0 = tcg_temp_new_i64();
224     TCGv_i64 t1 = tcg_temp_new_i64();
225 
226     tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
227     tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
228     tcg_gen_andi_i64(t0, t0, eval_big);
229     tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
230     tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
231     tcg_gen_andi_i64(t1, t1, eval_big);
232     tcg_gen_or_i64(t0, t0, t1);
233     /* if all bits are zero then all elements are not zero */
234     /* if some bit is non-zero then some element is zero */
235     tcg_gen_setcondi_i64(cond, t0, t0, 0);
236     tcg_gen_trunc_i64_tl(tresult, t0);
237     tcg_temp_free_i64(t0);
238     tcg_temp_free_i64(t1);
239 }
240 
241 static bool gen_msa_BxZ_V(DisasContext *ctx, int wt, int sa, TCGCond cond)
242 {
243     TCGv_i64 t0;
244 
245     if (!check_msa_enabled(ctx)) {
246         return true;
247     }
248 
249     if (ctx->hflags & MIPS_HFLAG_BMASK) {
250         gen_reserved_instruction(ctx);
251         return true;
252     }
253     t0 = tcg_temp_new_i64();
254     tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
255     tcg_gen_setcondi_i64(cond, t0, t0, 0);
256     tcg_gen_trunc_i64_tl(bcond, t0);
257     tcg_temp_free_i64(t0);
258 
259     ctx->btarget = ctx->base.pc_next + (sa << 2) + 4;
260 
261     ctx->hflags |= MIPS_HFLAG_BC;
262     ctx->hflags |= MIPS_HFLAG_BDS32;
263 
264     return true;
265 }
266 
267 static bool trans_BZ_V(DisasContext *ctx, arg_msa_bz *a)
268 {
269     return gen_msa_BxZ_V(ctx, a->wt, a->sa, TCG_COND_EQ);
270 }
271 
272 static bool trans_BNZ_V(DisasContext *ctx, arg_msa_bz *a)
273 {
274     return gen_msa_BxZ_V(ctx, a->wt, a->sa, TCG_COND_NE);
275 }
276 
277 static bool gen_msa_BxZ(DisasContext *ctx, int df, int wt, int sa, bool if_not)
278 {
279     if (!check_msa_enabled(ctx)) {
280         return true;
281     }
282 
283     if (ctx->hflags & MIPS_HFLAG_BMASK) {
284         gen_reserved_instruction(ctx);
285         return true;
286     }
287 
288     gen_check_zero_element(bcond, df, wt, if_not ? TCG_COND_EQ : TCG_COND_NE);
289 
290     ctx->btarget = ctx->base.pc_next + (sa << 2) + 4;
291     ctx->hflags |= MIPS_HFLAG_BC;
292     ctx->hflags |= MIPS_HFLAG_BDS32;
293 
294     return true;
295 }
296 
297 static bool trans_BZ(DisasContext *ctx, arg_msa_bz *a)
298 {
299     return gen_msa_BxZ(ctx, a->df, a->wt, a->sa, false);
300 }
301 
302 static bool trans_BNZ(DisasContext *ctx, arg_msa_bz *a)
303 {
304     return gen_msa_BxZ(ctx, a->df, a->wt, a->sa, true);
305 }
306 
307 static bool trans_msa_i8(DisasContext *ctx, arg_msa_i *a,
308                          gen_helper_piii *gen_msa_i8)
309 {
310     if (!check_msa_enabled(ctx)) {
311         return true;
312     }
313 
314     gen_msa_i8(cpu_env,
315                tcg_constant_i32(a->wd),
316                tcg_constant_i32(a->ws),
317                tcg_constant_i32(a->sa));
318 
319     return true;
320 }
321 
322 TRANS(ANDI,     trans_msa_i8, gen_helper_msa_andi_b);
323 TRANS(ORI,      trans_msa_i8, gen_helper_msa_ori_b);
324 TRANS(NORI,     trans_msa_i8, gen_helper_msa_nori_b);
325 TRANS(XORI,     trans_msa_i8, gen_helper_msa_xori_b);
326 TRANS(BMNZI,    trans_msa_i8, gen_helper_msa_bmnzi_b);
327 TRANS(BMZI,     trans_msa_i8, gen_helper_msa_bmzi_b);
328 TRANS(BSELI,    trans_msa_i8, gen_helper_msa_bseli_b);
329 
330 static bool trans_SHF(DisasContext *ctx, arg_msa_i *a)
331 {
332     if (a->df == DF_DOUBLE) {
333         return false;
334     }
335 
336     if (!check_msa_enabled(ctx)) {
337         return true;
338     }
339 
340     gen_helper_msa_shf_df(cpu_env,
341                           tcg_constant_i32(a->df),
342                           tcg_constant_i32(a->wd),
343                           tcg_constant_i32(a->ws),
344                           tcg_constant_i32(a->sa));
345 
346     return true;
347 }
348 
349 static bool trans_msa_i5(DisasContext *ctx, arg_msa_i *a,
350                          gen_helper_piiii *gen_msa_i5)
351 {
352     if (!check_msa_enabled(ctx)) {
353         return true;
354     }
355 
356     gen_msa_i5(cpu_env,
357                tcg_constant_i32(a->df),
358                tcg_constant_i32(a->wd),
359                tcg_constant_i32(a->ws),
360                tcg_constant_i32(a->sa));
361 
362     return true;
363 }
364 
365 TRANS(ADDVI,    trans_msa_i5, gen_helper_msa_addvi_df);
366 TRANS(SUBVI,    trans_msa_i5, gen_helper_msa_subvi_df);
367 TRANS(MAXI_S,   trans_msa_i5, gen_helper_msa_maxi_s_df);
368 TRANS(MAXI_U,   trans_msa_i5, gen_helper_msa_maxi_u_df);
369 TRANS(MINI_S,   trans_msa_i5, gen_helper_msa_mini_s_df);
370 TRANS(MINI_U,   trans_msa_i5, gen_helper_msa_mini_u_df);
371 TRANS(CLTI_S,   trans_msa_i5, gen_helper_msa_clti_s_df);
372 TRANS(CLTI_U,   trans_msa_i5, gen_helper_msa_clti_u_df);
373 TRANS(CLEI_S,   trans_msa_i5, gen_helper_msa_clei_s_df);
374 TRANS(CLEI_U,   trans_msa_i5, gen_helper_msa_clei_u_df);
375 TRANS(CEQI,     trans_msa_i5, gen_helper_msa_ceqi_df);
376 
377 static bool trans_LDI(DisasContext *ctx, arg_msa_ldi *a)
378 {
379     if (!check_msa_enabled(ctx)) {
380         return true;
381     }
382 
383     gen_helper_msa_ldi_df(cpu_env,
384                           tcg_constant_i32(a->df),
385                           tcg_constant_i32(a->wd),
386                           tcg_constant_i32(a->sa));
387 
388     return true;
389 }
390 
391 static bool trans_msa_bit(DisasContext *ctx, arg_msa_bit *a,
392                           gen_helper_piiii *gen_msa_bit)
393 {
394     if (a->df < 0) {
395         return false;
396     }
397 
398     if (!check_msa_enabled(ctx)) {
399         return true;
400     }
401 
402     gen_msa_bit(cpu_env,
403                 tcg_constant_i32(a->df),
404                 tcg_constant_i32(a->wd),
405                 tcg_constant_i32(a->ws),
406                 tcg_constant_i32(a->m));
407 
408     return true;
409 }
410 
411 TRANS(SLLI,     trans_msa_bit, gen_helper_msa_slli_df);
412 TRANS(SRAI,     trans_msa_bit, gen_helper_msa_srai_df);
413 TRANS(SRLI,     trans_msa_bit, gen_helper_msa_srli_df);
414 TRANS(BCLRI,    trans_msa_bit, gen_helper_msa_bclri_df);
415 TRANS(BSETI,    trans_msa_bit, gen_helper_msa_bseti_df);
416 TRANS(BNEGI,    trans_msa_bit, gen_helper_msa_bnegi_df);
417 TRANS(BINSLI,   trans_msa_bit, gen_helper_msa_binsli_df);
418 TRANS(BINSRI,   trans_msa_bit, gen_helper_msa_binsri_df);
419 TRANS(SAT_S,    trans_msa_bit, gen_helper_msa_sat_u_df);
420 TRANS(SAT_U,    trans_msa_bit, gen_helper_msa_sat_u_df);
421 TRANS(SRARI,    trans_msa_bit, gen_helper_msa_srari_df);
422 TRANS(SRLRI,    trans_msa_bit, gen_helper_msa_srlri_df);
423 
424 static bool trans_msa_3rf(DisasContext *ctx, arg_msa_r *a,
425                           gen_helper_piiii *gen_msa_3rf)
426 {
427     if (!check_msa_enabled(ctx)) {
428         return true;
429     }
430 
431     gen_msa_3rf(cpu_env,
432                 tcg_constant_i32(a->df),
433                 tcg_constant_i32(a->wd),
434                 tcg_constant_i32(a->ws),
435                 tcg_constant_i32(a->wt));
436 
437     return true;
438 }
439 
440 static bool trans_msa_3r(DisasContext *ctx, arg_msa_r *a,
441                          gen_helper_piii *gen_msa_3r)
442 {
443     if (!gen_msa_3r) {
444         return false;
445     }
446 
447     if (!check_msa_enabled(ctx)) {
448         return true;
449     }
450 
451     gen_msa_3r(cpu_env,
452                tcg_constant_i32(a->wd),
453                tcg_constant_i32(a->ws),
454                tcg_constant_i32(a->wt));
455 
456     return true;
457 }
458 
459 TRANS(AND_V,            trans_msa_3r,   gen_helper_msa_and_v);
460 TRANS(OR_V,             trans_msa_3r,   gen_helper_msa_or_v);
461 TRANS(NOR_V,            trans_msa_3r,   gen_helper_msa_nor_v);
462 TRANS(XOR_V,            trans_msa_3r,   gen_helper_msa_xor_v);
463 TRANS(BMNZ_V,           trans_msa_3r,   gen_helper_msa_bmnz_v);
464 TRANS(BMZ_V,            trans_msa_3r,   gen_helper_msa_bmz_v);
465 TRANS(BSEL_V,           trans_msa_3r,   gen_helper_msa_bsel_v);
466 
467 TRANS_DF_iii(SLL,       trans_msa_3r,   gen_helper_msa_sll);
468 TRANS_DF_iii(SRA,       trans_msa_3r,   gen_helper_msa_sra);
469 TRANS_DF_iii(SRL,       trans_msa_3r,   gen_helper_msa_srl);
470 TRANS_DF_iii(BCLR,      trans_msa_3r,   gen_helper_msa_bclr);
471 TRANS_DF_iii(BSET,      trans_msa_3r,   gen_helper_msa_bset);
472 TRANS_DF_iii(BNEG,      trans_msa_3r,   gen_helper_msa_bneg);
473 TRANS_DF_iii(BINSL,     trans_msa_3r,   gen_helper_msa_binsl);
474 TRANS_DF_iii(BINSR,     trans_msa_3r,   gen_helper_msa_binsr);
475 
476 TRANS_DF_iii(ADDV,      trans_msa_3r,   gen_helper_msa_addv);
477 TRANS_DF_iii(SUBV,      trans_msa_3r,   gen_helper_msa_subv);
478 TRANS_DF_iii(MAX_S,     trans_msa_3r,   gen_helper_msa_max_s);
479 TRANS_DF_iii(MAX_U,     trans_msa_3r,   gen_helper_msa_max_u);
480 TRANS_DF_iii(MIN_S,     trans_msa_3r,   gen_helper_msa_min_s);
481 TRANS_DF_iii(MIN_U,     trans_msa_3r,   gen_helper_msa_min_u);
482 TRANS_DF_iii(MAX_A,     trans_msa_3r,   gen_helper_msa_max_a);
483 TRANS_DF_iii(MIN_A,     trans_msa_3r,   gen_helper_msa_min_a);
484 
485 TRANS_DF_iii(CEQ,       trans_msa_3r,   gen_helper_msa_ceq);
486 TRANS_DF_iii(CLT_S,     trans_msa_3r,   gen_helper_msa_clt_s);
487 TRANS_DF_iii(CLT_U,     trans_msa_3r,   gen_helper_msa_clt_u);
488 TRANS_DF_iii(CLE_S,     trans_msa_3r,   gen_helper_msa_cle_s);
489 TRANS_DF_iii(CLE_U,     trans_msa_3r,   gen_helper_msa_cle_u);
490 
491 TRANS_DF_iii(ADD_A,     trans_msa_3r,   gen_helper_msa_add_a);
492 TRANS_DF_iii(ADDS_A,    trans_msa_3r,   gen_helper_msa_adds_a);
493 TRANS_DF_iii(ADDS_S,    trans_msa_3r,   gen_helper_msa_adds_s);
494 TRANS_DF_iii(ADDS_U,    trans_msa_3r,   gen_helper_msa_adds_u);
495 TRANS_DF_iii(AVE_S,     trans_msa_3r,   gen_helper_msa_ave_s);
496 TRANS_DF_iii(AVE_U,     trans_msa_3r,   gen_helper_msa_ave_u);
497 TRANS_DF_iii(AVER_S,    trans_msa_3r,   gen_helper_msa_aver_s);
498 TRANS_DF_iii(AVER_U,    trans_msa_3r,   gen_helper_msa_aver_u);
499 
500 TRANS_DF_iii(SUBS_S,    trans_msa_3r,   gen_helper_msa_subs_s);
501 TRANS_DF_iii(SUBS_U,    trans_msa_3r,   gen_helper_msa_subs_u);
502 TRANS_DF_iii(SUBSUS_U,  trans_msa_3r,   gen_helper_msa_subsus_u);
503 TRANS_DF_iii(SUBSUU_S,  trans_msa_3r,   gen_helper_msa_subsuu_s);
504 TRANS_DF_iii(ASUB_S,    trans_msa_3r,   gen_helper_msa_asub_s);
505 TRANS_DF_iii(ASUB_U,    trans_msa_3r,   gen_helper_msa_asub_u);
506 
507 TRANS_DF_iii(MULV,      trans_msa_3r,   gen_helper_msa_mulv);
508 TRANS_DF_iii(MADDV,     trans_msa_3r,   gen_helper_msa_maddv);
509 TRANS_DF_iii(MSUBV,     trans_msa_3r,   gen_helper_msa_msubv);
510 TRANS_DF_iii(DIV_S,     trans_msa_3r,   gen_helper_msa_div_s);
511 TRANS_DF_iii(DIV_U,     trans_msa_3r,   gen_helper_msa_div_u);
512 TRANS_DF_iii(MOD_S,     trans_msa_3r,   gen_helper_msa_mod_s);
513 TRANS_DF_iii(MOD_U,     trans_msa_3r,   gen_helper_msa_mod_u);
514 
515 TRANS_DF_iii_b(DOTP_S,  trans_msa_3r,   gen_helper_msa_dotp_s);
516 TRANS_DF_iii_b(DOTP_U,  trans_msa_3r,   gen_helper_msa_dotp_u);
517 TRANS_DF_iii_b(DPADD_S, trans_msa_3r,   gen_helper_msa_dpadd_s);
518 TRANS_DF_iii_b(DPADD_U, trans_msa_3r,   gen_helper_msa_dpadd_u);
519 TRANS_DF_iii_b(DPSUB_S, trans_msa_3r,   gen_helper_msa_dpsub_s);
520 TRANS_DF_iii_b(DPSUB_U, trans_msa_3r,   gen_helper_msa_dpsub_u);
521 
522 TRANS(SLD,              trans_msa_3rf,  gen_helper_msa_sld_df);
523 TRANS(SPLAT,            trans_msa_3rf,  gen_helper_msa_splat_df);
524 TRANS_DF_iii(PCKEV,     trans_msa_3r,   gen_helper_msa_pckev);
525 TRANS_DF_iii(PCKOD,     trans_msa_3r,   gen_helper_msa_pckod);
526 TRANS_DF_iii(ILVL,      trans_msa_3r,   gen_helper_msa_ilvl);
527 TRANS_DF_iii(ILVR,      trans_msa_3r,   gen_helper_msa_ilvr);
528 TRANS_DF_iii(ILVEV,     trans_msa_3r,   gen_helper_msa_ilvev);
529 TRANS_DF_iii(ILVOD,     trans_msa_3r,   gen_helper_msa_ilvod);
530 
531 TRANS(VSHF,             trans_msa_3rf,  gen_helper_msa_vshf_df);
532 TRANS_DF_iii(SRAR,      trans_msa_3r,   gen_helper_msa_srar);
533 TRANS_DF_iii(SRLR,      trans_msa_3r,   gen_helper_msa_srlr);
534 TRANS_DF_iii_b(HADD_S,  trans_msa_3r,   gen_helper_msa_hadd_s);
535 TRANS_DF_iii_b(HADD_U,  trans_msa_3r,   gen_helper_msa_hadd_u);
536 TRANS_DF_iii_b(HSUB_S,  trans_msa_3r,   gen_helper_msa_hsub_s);
537 TRANS_DF_iii_b(HSUB_U,  trans_msa_3r,   gen_helper_msa_hsub_u);
538 
539 static void gen_msa_elm_3e(DisasContext *ctx)
540 {
541 #define MASK_MSA_ELM_DF3E(op)   (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
542     uint8_t source = (ctx->opcode >> 11) & 0x1f;
543     uint8_t dest = (ctx->opcode >> 6) & 0x1f;
544     TCGv telm = tcg_temp_new();
545     TCGv_i32 tsr = tcg_const_i32(source);
546     TCGv_i32 tdt = tcg_const_i32(dest);
547 
548     switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
549     case OPC_CTCMSA:
550         gen_load_gpr(telm, source);
551         gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
552         break;
553     case OPC_CFCMSA:
554         gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
555         gen_store_gpr(telm, dest);
556         break;
557     case OPC_MOVE_V:
558         gen_helper_msa_move_v(cpu_env, tdt, tsr);
559         break;
560     default:
561         MIPS_INVAL("MSA instruction");
562         gen_reserved_instruction(ctx);
563         break;
564     }
565 
566     tcg_temp_free(telm);
567     tcg_temp_free_i32(tdt);
568     tcg_temp_free_i32(tsr);
569 }
570 
571 static bool trans_msa_elm(DisasContext *ctx, arg_msa_elm_df *a,
572                           gen_helper_piiii *gen_msa_elm_df)
573 {
574     if (a->df < 0) {
575         return false;
576     }
577 
578     if (!check_msa_enabled(ctx)) {
579         return true;
580     }
581 
582     gen_msa_elm_df(cpu_env,
583                    tcg_constant_i32(a->df),
584                    tcg_constant_i32(a->wd),
585                    tcg_constant_i32(a->ws),
586                    tcg_constant_i32(a->n));
587 
588     return true;
589 }
590 
591 TRANS(SLDI,   trans_msa_elm, gen_helper_msa_sldi_df);
592 TRANS(SPLATI, trans_msa_elm, gen_helper_msa_splati_df);
593 TRANS(INSVE,  trans_msa_elm, gen_helper_msa_insve_df);
594 
595 static void gen_msa_elm_df(DisasContext *ctx, uint32_t df, uint32_t n)
596 {
597 #define MASK_MSA_ELM(op)    (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
598     uint8_t ws = (ctx->opcode >> 11) & 0x1f;
599     uint8_t wd = (ctx->opcode >> 6) & 0x1f;
600 
601     TCGv_i32 tws = tcg_const_i32(ws);
602     TCGv_i32 twd = tcg_const_i32(wd);
603     TCGv_i32 tn  = tcg_const_i32(n);
604 
605     switch (MASK_MSA_ELM(ctx->opcode)) {
606     case OPC_COPY_S_df:
607     case OPC_COPY_U_df:
608     case OPC_INSERT_df:
609 #if !defined(TARGET_MIPS64)
610         /* Double format valid only for MIPS64 */
611         if (df == DF_DOUBLE) {
612             gen_reserved_instruction(ctx);
613             break;
614         }
615         if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
616               (df == DF_WORD)) {
617             gen_reserved_instruction(ctx);
618             break;
619         }
620 #endif
621         switch (MASK_MSA_ELM(ctx->opcode)) {
622         case OPC_COPY_S_df:
623             if (likely(wd != 0)) {
624                 switch (df) {
625                 case DF_BYTE:
626                     gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
627                     break;
628                 case DF_HALF:
629                     gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
630                     break;
631                 case DF_WORD:
632                     gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
633                     break;
634 #if defined(TARGET_MIPS64)
635                 case DF_DOUBLE:
636                     gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
637                     break;
638 #endif
639                 default:
640                     assert(0);
641                 }
642             }
643             break;
644         case OPC_COPY_U_df:
645             if (likely(wd != 0)) {
646                 switch (df) {
647                 case DF_BYTE:
648                     gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
649                     break;
650                 case DF_HALF:
651                     gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
652                     break;
653 #if defined(TARGET_MIPS64)
654                 case DF_WORD:
655                     gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
656                     break;
657 #endif
658                 default:
659                     assert(0);
660                 }
661             }
662             break;
663         case OPC_INSERT_df:
664             switch (df) {
665             case DF_BYTE:
666                 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
667                 break;
668             case DF_HALF:
669                 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
670                 break;
671             case DF_WORD:
672                 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
673                 break;
674 #if defined(TARGET_MIPS64)
675             case DF_DOUBLE:
676                 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
677                 break;
678 #endif
679             default:
680                 assert(0);
681             }
682             break;
683         }
684         break;
685     default:
686         MIPS_INVAL("MSA instruction");
687         gen_reserved_instruction(ctx);
688     }
689     tcg_temp_free_i32(twd);
690     tcg_temp_free_i32(tws);
691     tcg_temp_free_i32(tn);
692 }
693 
694 static void gen_msa_elm(DisasContext *ctx)
695 {
696     uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
697     uint32_t df = 0, n = 0;
698 
699     if ((dfn & 0x30) == 0x00) {
700         n = dfn & 0x0f;
701         df = DF_BYTE;
702     } else if ((dfn & 0x38) == 0x20) {
703         n = dfn & 0x07;
704         df = DF_HALF;
705     } else if ((dfn & 0x3c) == 0x30) {
706         n = dfn & 0x03;
707         df = DF_WORD;
708     } else if ((dfn & 0x3e) == 0x38) {
709         n = dfn & 0x01;
710         df = DF_DOUBLE;
711     } else if (dfn == 0x3E) {
712         /* CTCMSA, CFCMSA, MOVE.V */
713         gen_msa_elm_3e(ctx);
714         return;
715     } else {
716         gen_reserved_instruction(ctx);
717         return;
718     }
719 
720     gen_msa_elm_df(ctx, df, n);
721 }
722 
723 TRANS(FCAF,     trans_msa_3rf, gen_helper_msa_fcaf_df);
724 TRANS(FCUN,     trans_msa_3rf, gen_helper_msa_fcun_df);
725 TRANS(FCEQ,     trans_msa_3rf, gen_helper_msa_fceq_df);
726 TRANS(FCUEQ,    trans_msa_3rf, gen_helper_msa_fcueq_df);
727 TRANS(FCLT,     trans_msa_3rf, gen_helper_msa_fclt_df);
728 TRANS(FCULT,    trans_msa_3rf, gen_helper_msa_fcult_df);
729 TRANS(FCLE,     trans_msa_3rf, gen_helper_msa_fcle_df);
730 TRANS(FCULE,    trans_msa_3rf, gen_helper_msa_fcule_df);
731 TRANS(FSAF,     trans_msa_3rf, gen_helper_msa_fsaf_df);
732 TRANS(FSUN,     trans_msa_3rf, gen_helper_msa_fsun_df);
733 TRANS(FSEQ,     trans_msa_3rf, gen_helper_msa_fseq_df);
734 TRANS(FSUEQ,    trans_msa_3rf, gen_helper_msa_fsueq_df);
735 TRANS(FSLT,     trans_msa_3rf, gen_helper_msa_fslt_df);
736 TRANS(FSULT,    trans_msa_3rf, gen_helper_msa_fsult_df);
737 TRANS(FSLE,     trans_msa_3rf, gen_helper_msa_fsle_df);
738 TRANS(FSULE,    trans_msa_3rf, gen_helper_msa_fsule_df);
739 
740 TRANS(FADD,     trans_msa_3rf, gen_helper_msa_fadd_df);
741 TRANS(FSUB,     trans_msa_3rf, gen_helper_msa_fsub_df);
742 TRANS(FMUL,     trans_msa_3rf, gen_helper_msa_fmul_df);
743 TRANS(FDIV,     trans_msa_3rf, gen_helper_msa_fdiv_df);
744 TRANS(FMADD,    trans_msa_3rf, gen_helper_msa_fmadd_df);
745 TRANS(FMSUB,    trans_msa_3rf, gen_helper_msa_fmsub_df);
746 TRANS(FEXP2,    trans_msa_3rf, gen_helper_msa_fexp2_df);
747 TRANS(FEXDO,    trans_msa_3rf, gen_helper_msa_fexdo_df);
748 TRANS(FTQ,      trans_msa_3rf, gen_helper_msa_ftq_df);
749 TRANS(FMIN,     trans_msa_3rf, gen_helper_msa_fmin_df);
750 TRANS(FMIN_A,   trans_msa_3rf, gen_helper_msa_fmin_a_df);
751 TRANS(FMAX,     trans_msa_3rf, gen_helper_msa_fmax_df);
752 TRANS(FMAX_A,   trans_msa_3rf, gen_helper_msa_fmax_a_df);
753 
754 TRANS(FCOR,     trans_msa_3rf, gen_helper_msa_fcor_df);
755 TRANS(FCUNE,    trans_msa_3rf, gen_helper_msa_fcune_df);
756 TRANS(FCNE,     trans_msa_3rf, gen_helper_msa_fcne_df);
757 TRANS(MUL_Q,    trans_msa_3rf, gen_helper_msa_mul_q_df);
758 TRANS(MADD_Q,   trans_msa_3rf, gen_helper_msa_madd_q_df);
759 TRANS(MSUB_Q,   trans_msa_3rf, gen_helper_msa_msub_q_df);
760 TRANS(FSOR,     trans_msa_3rf, gen_helper_msa_fsor_df);
761 TRANS(FSUNE,    trans_msa_3rf, gen_helper_msa_fsune_df);
762 TRANS(FSNE,     trans_msa_3rf, gen_helper_msa_fsne_df);
763 TRANS(MULR_Q,   trans_msa_3rf, gen_helper_msa_mulr_q_df);
764 TRANS(MADDR_Q,  trans_msa_3rf, gen_helper_msa_maddr_q_df);
765 TRANS(MSUBR_Q,  trans_msa_3rf, gen_helper_msa_msubr_q_df);
766 
767 static bool trans_msa_2r(DisasContext *ctx, arg_msa_r *a,
768                          gen_helper_pii *gen_msa_2r)
769 {
770     if (!check_msa_enabled(ctx)) {
771         return true;
772     }
773 
774     gen_msa_2r(cpu_env, tcg_constant_i32(a->wd), tcg_constant_i32(a->ws));
775 
776     return true;
777 }
778 
779 TRANS_DF_ii(PCNT, trans_msa_2r, gen_helper_msa_pcnt);
780 TRANS_DF_ii(NLOC, trans_msa_2r, gen_helper_msa_nloc);
781 TRANS_DF_ii(NLZC, trans_msa_2r, gen_helper_msa_nlzc);
782 
783 static bool trans_FILL(DisasContext *ctx, arg_msa_r *a)
784 {
785     if (TARGET_LONG_BITS != 64 && a->df == DF_DOUBLE) {
786         /* Double format valid only for MIPS64 */
787         return false;
788     }
789 
790     if (!check_msa_enabled(ctx)) {
791         return true;
792     }
793 
794     gen_helper_msa_fill_df(cpu_env,
795                            tcg_constant_i32(a->df),
796                            tcg_constant_i32(a->wd),
797                            tcg_constant_i32(a->ws));
798 
799     return true;
800 }
801 
802 static bool trans_msa_2rf(DisasContext *ctx, arg_msa_r *a,
803                           gen_helper_piii *gen_msa_2rf)
804 {
805     if (!check_msa_enabled(ctx)) {
806         return true;
807     }
808 
809     gen_msa_2rf(cpu_env,
810                 tcg_constant_i32(a->df),
811                 tcg_constant_i32(a->wd),
812                 tcg_constant_i32(a->ws));
813 
814     return true;
815 }
816 
817 TRANS(FCLASS,   trans_msa_2rf, gen_helper_msa_fclass_df);
818 TRANS(FTRUNC_S, trans_msa_2rf, gen_helper_msa_fclass_df);
819 TRANS(FTRUNC_U, trans_msa_2rf, gen_helper_msa_ftrunc_s_df);
820 TRANS(FSQRT,    trans_msa_2rf, gen_helper_msa_fsqrt_df);
821 TRANS(FRSQRT,   trans_msa_2rf, gen_helper_msa_frsqrt_df);
822 TRANS(FRCP,     trans_msa_2rf, gen_helper_msa_frcp_df);
823 TRANS(FRINT,    trans_msa_2rf, gen_helper_msa_frint_df);
824 TRANS(FLOG2,    trans_msa_2rf, gen_helper_msa_flog2_df);
825 TRANS(FEXUPL,   trans_msa_2rf, gen_helper_msa_fexupl_df);
826 TRANS(FEXUPR,   trans_msa_2rf, gen_helper_msa_fexupr_df);
827 TRANS(FFQL,     trans_msa_2rf, gen_helper_msa_ffql_df);
828 TRANS(FFQR,     trans_msa_2rf, gen_helper_msa_ffqr_df);
829 TRANS(FTINT_S,  trans_msa_2rf, gen_helper_msa_ftint_s_df);
830 TRANS(FTINT_U,  trans_msa_2rf, gen_helper_msa_ftint_u_df);
831 TRANS(FFINT_S,  trans_msa_2rf, gen_helper_msa_ffint_s_df);
832 TRANS(FFINT_U,  trans_msa_2rf, gen_helper_msa_ffint_u_df);
833 
834 static bool trans_MSA(DisasContext *ctx, arg_MSA *a)
835 {
836     uint32_t opcode = ctx->opcode;
837 
838     if (!check_msa_enabled(ctx)) {
839         return true;
840     }
841 
842     switch (MASK_MSA_MINOR(opcode)) {
843     case OPC_MSA_ELM:
844         gen_msa_elm(ctx);
845         break;
846     default:
847         MIPS_INVAL("MSA instruction");
848         gen_reserved_instruction(ctx);
849         break;
850     }
851 
852     return true;
853 }
854 
855 static bool trans_msa_ldst(DisasContext *ctx, arg_msa_i *a,
856                            gen_helper_piv *gen_msa_ldst)
857 {
858     TCGv taddr;
859 
860     if (!check_msa_enabled(ctx)) {
861         return true;
862     }
863 
864     taddr = tcg_temp_new();
865 
866     gen_base_offset_addr(ctx, taddr, a->ws, a->sa << a->df);
867     gen_msa_ldst(cpu_env, tcg_constant_i32(a->wd), taddr);
868 
869     tcg_temp_free(taddr);
870 
871     return true;
872 }
873 
874 TRANS_DF_iv(LD, trans_msa_ldst, gen_helper_msa_ld);
875 TRANS_DF_iv(ST, trans_msa_ldst, gen_helper_msa_st);
876 
877 static bool trans_LSA(DisasContext *ctx, arg_r *a)
878 {
879     return gen_lsa(ctx, a->rd, a->rt, a->rs, a->sa);
880 }
881 
882 static bool trans_DLSA(DisasContext *ctx, arg_r *a)
883 {
884     if (TARGET_LONG_BITS != 64) {
885         return false;
886     }
887     return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa);
888 }
889