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