1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "tcg/tcg-op.h"
12#include "tcg/tcg-op-gvec.h"
13#include "exec/helper-gen.h"
14#include "translate.h"
15
16
17#include "decode-tx79.c.inc"
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
36{
37 if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
38 return true;
39 }
40 return false;
41}
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
68{
69 gen_store_gpr(cpu_HI[1], a->rd);
70
71 return true;
72}
73
74static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
75{
76 gen_store_gpr(cpu_LO[1], a->rd);
77
78 return true;
79}
80
81static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
82{
83 gen_load_gpr(cpu_HI[1], a->rs);
84
85 return true;
86}
87
88static bool trans_MTLO1(DisasContext *ctx, arg_r *a)
89{
90 gen_load_gpr(cpu_LO[1], a->rs);
91
92 return true;
93}
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119static bool trans_parallel_arith(DisasContext *ctx, arg_r *a,
120 void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
121{
122 TCGv_i64 ax, bx;
123
124 if (a->rd == 0) {
125
126 return true;
127 }
128
129 ax = tcg_temp_new_i64();
130 bx = tcg_temp_new_i64();
131
132
133 gen_load_gpr(ax, a->rs);
134 gen_load_gpr(bx, a->rt);
135 gen_logic_i64(cpu_gpr[a->rd], ax, bx);
136
137
138 gen_load_gpr_hi(ax, a->rs);
139 gen_load_gpr_hi(bx, a->rt);
140 gen_logic_i64(cpu_gpr_hi[a->rd], ax, bx);
141
142 tcg_temp_free(bx);
143 tcg_temp_free(ax);
144
145 return true;
146}
147
148
149static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
150{
151 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
152}
153
154
155static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
156{
157 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
158}
159
160
161static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
162{
163 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
164}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192static bool trans_PAND(DisasContext *ctx, arg_r *a)
193{
194 return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
195}
196
197
198static bool trans_POR(DisasContext *ctx, arg_r *a)
199{
200 return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
201}
202
203
204static bool trans_PXOR(DisasContext *ctx, arg_r *a)
205{
206 return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
207}
208
209
210static bool trans_PNOR(DisasContext *ctx, arg_r *a)
211{
212 return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
213}
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
241 TCGCond cond, unsigned wlen)
242{
243 TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
244
245 if (a->rd == 0) {
246
247 return true;
248 }
249
250 c0 = tcg_const_tl(0);
251 c1 = tcg_const_tl(0xffffffff);
252 ax = tcg_temp_new_i64();
253 bx = tcg_temp_new_i64();
254 t0 = tcg_temp_new_i64();
255 t1 = tcg_temp_new_i64();
256 t2 = tcg_temp_new_i64();
257
258
259 gen_load_gpr(ax, a->rs);
260 gen_load_gpr(bx, a->rt);
261 for (int i = 0; i < (64 / wlen); i++) {
262 tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
263 tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
264 tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
265 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
266 }
267
268 gen_load_gpr_hi(ax, a->rs);
269 gen_load_gpr_hi(bx, a->rt);
270 for (int i = 0; i < (64 / wlen); i++) {
271 tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
272 tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
273 tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
274 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
275 }
276
277 tcg_temp_free(t2);
278 tcg_temp_free(t1);
279 tcg_temp_free(t0);
280 tcg_temp_free(bx);
281 tcg_temp_free(ax);
282 tcg_temp_free(c1);
283 tcg_temp_free(c0);
284
285 return true;
286}
287
288
289static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
290{
291 return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
292}
293
294
295static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
296{
297 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
298}
299
300
301static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
302{
303 return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
304}
305
306
307static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
308{
309 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
310}
311
312
313static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
314{
315 return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
316}
317
318
319static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
320{
321 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
322}
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337static bool trans_LQ(DisasContext *ctx, arg_i *a)
338{
339 TCGv_i64 t0;
340 TCGv addr;
341
342 if (a->rt == 0) {
343
344 return true;
345 }
346
347 t0 = tcg_temp_new_i64();
348 addr = tcg_temp_new();
349
350 gen_base_offset_addr(ctx, addr, a->base, a->offset);
351
352
353
354
355 tcg_gen_andi_tl(addr, addr, ~0xf);
356
357
358 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
359 gen_store_gpr(t0, a->rt);
360
361
362 tcg_gen_addi_i64(addr, addr, 8);
363 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
364 gen_store_gpr_hi(t0, a->rt);
365
366 tcg_temp_free(t0);
367 tcg_temp_free(addr);
368
369 return true;
370}
371
372static bool trans_SQ(DisasContext *ctx, arg_i *a)
373{
374 TCGv_i64 t0 = tcg_temp_new_i64();
375 TCGv addr = tcg_temp_new();
376
377 gen_base_offset_addr(ctx, addr, a->base, a->offset);
378
379
380
381
382 tcg_gen_andi_tl(addr, addr, ~0xf);
383
384
385 gen_load_gpr(t0, a->rt);
386 tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
387
388
389 tcg_gen_addi_i64(addr, addr, 8);
390 gen_load_gpr_hi(t0, a->rt);
391 tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
392
393 tcg_temp_free(addr);
394 tcg_temp_free(t0);
395
396 return true;
397}
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440static bool trans_PPACW(DisasContext *ctx, arg_r *a)
441{
442 TCGv_i64 a0, b0, t0;
443
444 if (a->rd == 0) {
445
446 return true;
447 }
448
449 a0 = tcg_temp_new_i64();
450 b0 = tcg_temp_new_i64();
451 t0 = tcg_temp_new_i64();
452
453 gen_load_gpr(a0, a->rs);
454 gen_load_gpr(b0, a->rt);
455
456 gen_load_gpr_hi(t0, a->rt);
457 tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
458
459 gen_load_gpr_hi(t0, a->rs);
460 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
461
462 tcg_temp_free(t0);
463 tcg_temp_free(b0);
464 tcg_temp_free(a0);
465
466 return true;
467}
468
469static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
470{
471 tcg_gen_deposit_i64(dl, b, a, 32, 32);
472 tcg_gen_shri_i64(b, b, 32);
473 tcg_gen_deposit_i64(dh, a, b, 0, 32);
474}
475
476static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
477{
478 TCGv_i64 ax, bx;
479
480 if (a->rd == 0) {
481
482 return true;
483 }
484
485 ax = tcg_temp_new_i64();
486 bx = tcg_temp_new_i64();
487
488 gen_load_gpr(ax, a->rs);
489 gen_load_gpr(bx, a->rt);
490
491
492 for (int i = 0; i < 64 / (2 * wlen); i++) {
493 tcg_gen_deposit_i64(cpu_gpr[a->rd],
494 cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
495 tcg_gen_deposit_i64(cpu_gpr[a->rd],
496 cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
497 tcg_gen_shri_i64(bx, bx, wlen);
498 tcg_gen_shri_i64(ax, ax, wlen);
499 }
500
501 for (int i = 0; i < 64 / (2 * wlen); i++) {
502 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
503 cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
504 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
505 cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
506 tcg_gen_shri_i64(bx, bx, wlen);
507 tcg_gen_shri_i64(ax, ax, wlen);
508 }
509
510 tcg_temp_free(bx);
511 tcg_temp_free(ax);
512
513 return true;
514}
515
516
517static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
518{
519 return trans_PEXTLx(ctx, a, 8);
520}
521
522
523static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
524{
525 return trans_PEXTLx(ctx, a, 16);
526}
527
528
529static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
530{
531 TCGv_i64 ax, bx;
532
533 if (a->rd == 0) {
534
535 return true;
536 }
537
538 ax = tcg_temp_new_i64();
539 bx = tcg_temp_new_i64();
540
541 gen_load_gpr(ax, a->rs);
542 gen_load_gpr(bx, a->rt);
543 gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
544
545 tcg_temp_free(bx);
546 tcg_temp_free(ax);
547
548 return true;
549}
550
551
552static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
553{
554 TCGv_i64 ax, bx;
555
556 if (a->rd == 0) {
557
558 return true;
559 }
560
561 ax = tcg_temp_new_i64();
562 bx = tcg_temp_new_i64();
563
564 gen_load_gpr_hi(ax, a->rs);
565 gen_load_gpr_hi(bx, a->rt);
566 gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
567
568 tcg_temp_free(bx);
569 tcg_temp_free(ax);
570
571 return true;
572}
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596static bool trans_PCPYH(DisasContext *s, arg_r *a)
597{
598 if (a->rd == 0) {
599
600 return true;
601 }
602
603 if (a->rt == 0) {
604 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
605 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
606 return true;
607 }
608
609 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
610 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
611 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
612 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
613
614 return true;
615}
616
617
618static bool trans_PCPYLD(DisasContext *s, arg_r *a)
619{
620 if (a->rd == 0) {
621
622 return true;
623 }
624
625 if (a->rs == 0) {
626 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
627 } else {
628 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
629 }
630
631 if (a->rt == 0) {
632 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
633 } else if (a->rd != a->rt) {
634 tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
635 }
636
637 return true;
638}
639
640
641static bool trans_PCPYUD(DisasContext *s, arg_r *a)
642{
643 if (a->rd == 0) {
644
645 return true;
646 }
647
648 gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
649
650 if (a->rt == 0) {
651 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
652 } else if (a->rd != a->rt) {
653 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
654 }
655
656 return true;
657}
658
659
660static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
661{
662 TCGv_i64 ax;
663
664 if (a->rd == 0) {
665
666 return true;
667 }
668 if (a->rt == 0) {
669 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
670 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
671 return true;
672 }
673
674 ax = tcg_temp_new_i64();
675
676 tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
677 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
678
679 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
680 tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
681
682 tcg_temp_free(ax);
683
684 return true;
685}
686