target/mips/tx79: Introduce SQ opcode (Store Quadword)
[qemu/ar7.git] / target / mips / tcg / tx79_translate.c
blob395d6afa1f105c2ecb61095e18972e17c696a9a3
1 /*
2 * Toshiba TX79-specific instructions translation routines
4 * Copyright (c) 2018 Fredrik Noring
5 * Copyright (c) 2021 Philippe Mathieu-Daudé
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
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"
16 /* Include the auto-generated decoder. */
17 #include "decode-tx79.c.inc"
20 * Overview of the TX79-specific instruction set
21 * =============================================
23 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
24 * are only used by the specific quadword (128-bit) LQ/SQ load/store
25 * instructions and certain multimedia instructions (MMIs). These MMIs
26 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
27 * or sixteen 8-bit paths.
29 * Reference:
31 * The Toshiba TX System RISC TX79 Core Architecture manual,
32 * https://wiki.qemu.org/File:C790.pdf
35 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
37 if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
38 return true;
40 return false;
44 * Three-Operand Multiply and Multiply-Add (4 instructions)
45 * --------------------------------------------------------
46 * MADD [rd,] rs, rt Multiply/Add
47 * MADDU [rd,] rs, rt Multiply/Add Unsigned
48 * MULT [rd,] rs, rt Multiply (3-operand)
49 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
53 * Multiply Instructions for Pipeline 1 (10 instructions)
54 * ------------------------------------------------------
55 * MULT1 [rd,] rs, rt Multiply Pipeline 1
56 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
57 * DIV1 rs, rt Divide Pipeline 1
58 * DIVU1 rs, rt Divide Unsigned Pipeline 1
59 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
60 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
61 * MFHI1 rd Move From HI1 Register
62 * MFLO1 rd Move From LO1 Register
63 * MTHI1 rs Move To HI1 Register
64 * MTLO1 rs Move To LO1 Register
67 static bool trans_MFHI1(DisasContext *ctx, arg_rtype *a)
69 gen_store_gpr(cpu_HI[1], a->rd);
71 return true;
74 static bool trans_MFLO1(DisasContext *ctx, arg_rtype *a)
76 gen_store_gpr(cpu_LO[1], a->rd);
78 return true;
81 static bool trans_MTHI1(DisasContext *ctx, arg_rtype *a)
83 gen_load_gpr(cpu_HI[1], a->rs);
85 return true;
88 static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a)
90 gen_load_gpr(cpu_LO[1], a->rs);
92 return true;
96 * Arithmetic (19 instructions)
97 * ----------------------------
98 * PADDB rd, rs, rt Parallel Add Byte
99 * PSUBB rd, rs, rt Parallel Subtract Byte
100 * PADDH rd, rs, rt Parallel Add Halfword
101 * PSUBH rd, rs, rt Parallel Subtract Halfword
102 * PADDW rd, rs, rt Parallel Add Word
103 * PSUBW rd, rs, rt Parallel Subtract Word
104 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
105 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
106 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
107 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
108 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
109 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
110 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
111 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
112 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
113 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
114 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
115 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
116 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
119 static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *a,
120 void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
122 TCGv_i64 ax, bx;
124 if (a->rd == 0) {
125 /* nop */
126 return true;
129 ax = tcg_temp_new_i64();
130 bx = tcg_temp_new_i64();
132 /* Lower half */
133 gen_load_gpr(ax, a->rs);
134 gen_load_gpr(bx, a->rt);
135 gen_logic_i64(cpu_gpr[a->rd], ax, bx);
137 /* Upper half */
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);
142 tcg_temp_free(bx);
143 tcg_temp_free(ax);
145 return true;
148 /* Parallel Subtract Byte */
149 static bool trans_PSUBB(DisasContext *ctx, arg_rtype *a)
151 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
154 /* Parallel Subtract Halfword */
155 static bool trans_PSUBH(DisasContext *ctx, arg_rtype *a)
157 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
160 /* Parallel Subtract Word */
161 static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a)
163 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
167 * Min/Max (4 instructions)
168 * ------------------------
169 * PMAXH rd, rs, rt Parallel Maximum Halfword
170 * PMINH rd, rs, rt Parallel Minimum Halfword
171 * PMAXW rd, rs, rt Parallel Maximum Word
172 * PMINW rd, rs, rt Parallel Minimum Word
176 * Absolute (2 instructions)
177 * -------------------------
178 * PABSH rd, rt Parallel Absolute Halfword
179 * PABSW rd, rt Parallel Absolute Word
183 * Logical (4 instructions)
184 * ------------------------
185 * PAND rd, rs, rt Parallel AND
186 * POR rd, rs, rt Parallel OR
187 * PXOR rd, rs, rt Parallel XOR
188 * PNOR rd, rs, rt Parallel NOR
191 /* Parallel And */
192 static bool trans_PAND(DisasContext *ctx, arg_rtype *a)
194 return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
197 /* Parallel Or */
198 static bool trans_POR(DisasContext *ctx, arg_rtype *a)
200 return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
203 /* Parallel Exclusive Or */
204 static bool trans_PXOR(DisasContext *ctx, arg_rtype *a)
206 return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
209 /* Parallel Not Or */
210 static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
212 return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
216 * Shift (9 instructions)
217 * ----------------------
218 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
219 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
220 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
221 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
222 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
223 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
224 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
225 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
226 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
230 * Compare (6 instructions)
231 * ------------------------
232 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
233 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
234 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
235 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
236 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
237 * PCEQW rd, rs, rt Parallel Compare for Equal Word
240 static bool trans_parallel_compare(DisasContext *ctx, arg_rtype *a,
241 TCGCond cond, unsigned wlen)
243 TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
245 if (a->rd == 0) {
246 /* nop */
247 return true;
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();
258 /* Lower half */
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);
267 /* Upper half */
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);
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);
285 return true;
288 /* Parallel Compare for Greater Than Byte */
289 static bool trans_PCGTB(DisasContext *ctx, arg_rtype *a)
291 return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
294 /* Parallel Compare for Equal Byte */
295 static bool trans_PCEQB(DisasContext *ctx, arg_rtype *a)
297 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
300 /* Parallel Compare for Greater Than Halfword */
301 static bool trans_PCGTH(DisasContext *ctx, arg_rtype *a)
303 return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
306 /* Parallel Compare for Equal Halfword */
307 static bool trans_PCEQH(DisasContext *ctx, arg_rtype *a)
309 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
312 /* Parallel Compare for Greater Than Word */
313 static bool trans_PCGTW(DisasContext *ctx, arg_rtype *a)
315 return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
318 /* Parallel Compare for Equal Word */
319 static bool trans_PCEQW(DisasContext *ctx, arg_rtype *a)
321 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
325 * LZC (1 instruction)
326 * -------------------
327 * PLZCW rd, rs Parallel Leading Zero or One Count Word
331 * Quadword Load and Store (2 instructions)
332 * ----------------------------------------
333 * LQ rt, offset(base) Load Quadword
334 * SQ rt, offset(base) Store Quadword
337 static bool trans_LQ(DisasContext *ctx, arg_itype *a)
339 TCGv_i64 t0;
340 TCGv addr;
342 if (a->rt == 0) {
343 /* nop */
344 return true;
347 t0 = tcg_temp_new_i64();
348 addr = tcg_temp_new();
350 gen_base_offset_addr(ctx, addr, a->base, a->offset);
352 * Clear least-significant four bits of the effective
353 * address, effectively creating an aligned address.
355 tcg_gen_andi_tl(addr, addr, ~0xf);
357 /* Lower half */
358 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
359 gen_store_gpr(t0, a->rt);
361 /* Upper half */
362 tcg_gen_addi_i64(addr, addr, 8);
363 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
364 gen_store_gpr_hi(t0, a->rt);
366 tcg_temp_free(t0);
367 tcg_temp_free(addr);
369 return true;
372 static bool trans_SQ(DisasContext *ctx, arg_itype *a)
374 TCGv_i64 t0 = tcg_temp_new_i64();
375 TCGv addr = tcg_temp_new();
377 gen_base_offset_addr(ctx, addr, a->base, a->offset);
379 * Clear least-significant four bits of the effective
380 * address, effectively creating an aligned address.
382 tcg_gen_andi_tl(addr, addr, ~0xf);
384 /* Lower half */
385 gen_load_gpr(t0, a->rt);
386 tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
388 /* Upper half */
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_TEQ);
393 tcg_temp_free(addr);
394 tcg_temp_free(t0);
396 return true;
400 * Multiply and Divide (19 instructions)
401 * -------------------------------------
402 * PMULTW rd, rs, rt Parallel Multiply Word
403 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
404 * PDIVW rs, rt Parallel Divide Word
405 * PDIVUW rs, rt Parallel Divide Unsigned Word
406 * PMADDW rd, rs, rt Parallel Multiply-Add Word
407 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
408 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
409 * PMULTH rd, rs, rt Parallel Multiply Halfword
410 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
411 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
412 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
413 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
414 * PDIVBW rs, rt Parallel Divide Broadcast Word
415 * PMFHI rd Parallel Move From HI Register
416 * PMFLO rd Parallel Move From LO Register
417 * PMTHI rs Parallel Move To HI Register
418 * PMTLO rs Parallel Move To LO Register
419 * PMFHL rd Parallel Move From HI/LO Register
420 * PMTHL rs Parallel Move To HI/LO Register
424 * Pack/Extend (11 instructions)
425 * -----------------------------
426 * PPAC5 rd, rt Parallel Pack to 5 bits
427 * PPACB rd, rs, rt Parallel Pack to Byte
428 * PPACH rd, rs, rt Parallel Pack to Halfword
429 * PPACW rd, rs, rt Parallel Pack to Word
430 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
431 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
432 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
433 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
434 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
435 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
436 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
439 /* Parallel Pack to Word */
440 static bool trans_PPACW(DisasContext *ctx, arg_rtype *a)
442 TCGv_i64 a0, b0, t0;
444 if (a->rd == 0) {
445 /* nop */
446 return true;
449 a0 = tcg_temp_new_i64();
450 b0 = tcg_temp_new_i64();
451 t0 = tcg_temp_new_i64();
453 gen_load_gpr(a0, a->rs);
454 gen_load_gpr(b0, a->rt);
456 gen_load_gpr_hi(t0, a->rt); /* b1 */
457 tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
459 gen_load_gpr_hi(t0, a->rs); /* a1 */
460 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
462 tcg_temp_free(t0);
463 tcg_temp_free(b0);
464 tcg_temp_free(a0);
466 return true;
469 static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
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);
476 static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
478 TCGv_i64 ax, bx;
480 if (a->rd == 0) {
481 /* nop */
482 return true;
485 ax = tcg_temp_new_i64();
486 bx = tcg_temp_new_i64();
488 gen_load_gpr(ax, a->rs);
489 gen_load_gpr(bx, a->rt);
491 /* Lower half */
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);
500 /* Upper half */
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);
510 tcg_temp_free(bx);
511 tcg_temp_free(ax);
513 return true;
516 /* Parallel Extend Lower from Byte */
517 static bool trans_PEXTLB(DisasContext *ctx, arg_rtype *a)
519 return trans_PEXTLx(ctx, a, 8);
522 /* Parallel Extend Lower from Halfword */
523 static bool trans_PEXTLH(DisasContext *ctx, arg_rtype *a)
525 return trans_PEXTLx(ctx, a, 16);
528 /* Parallel Extend Lower from Word */
529 static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
531 TCGv_i64 ax, bx;
533 if (a->rd == 0) {
534 /* nop */
535 return true;
538 ax = tcg_temp_new_i64();
539 bx = tcg_temp_new_i64();
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);
545 tcg_temp_free(bx);
546 tcg_temp_free(ax);
548 return true;
551 /* Parallel Extend Upper from Word */
552 static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
554 TCGv_i64 ax, bx;
556 if (a->rd == 0) {
557 /* nop */
558 return true;
561 ax = tcg_temp_new_i64();
562 bx = tcg_temp_new_i64();
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);
568 tcg_temp_free(bx);
569 tcg_temp_free(ax);
571 return true;
575 * Others (16 instructions)
576 * ------------------------
577 * PCPYH rd, rt Parallel Copy Halfword
578 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
579 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
580 * PREVH rd, rt Parallel Reverse Halfword
581 * PINTH rd, rs, rt Parallel Interleave Halfword
582 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
583 * PEXEH rd, rt Parallel Exchange Even Halfword
584 * PEXCH rd, rt Parallel Exchange Center Halfword
585 * PEXEW rd, rt Parallel Exchange Even Word
586 * PEXCW rd, rt Parallel Exchange Center Word
587 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
588 * MFSA rd Move from Shift Amount Register
589 * MTSA rs Move to Shift Amount Register
590 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
591 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
592 * PROT3W rd, rt Parallel Rotate 3 Words
595 /* Parallel Copy Halfword */
596 static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
598 if (a->rd == 0) {
599 /* nop */
600 return true;
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;
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);
614 return true;
617 /* Parallel Copy Lower Doubleword */
618 static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
620 if (a->rd == 0) {
621 /* nop */
622 return true;
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]);
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]);
637 return true;
640 /* Parallel Copy Upper Doubleword */
641 static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
643 if (a->rd == 0) {
644 /* nop */
645 return true;
648 gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
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]);
656 return true;
659 /* Parallel Rotate 3 Words Left */
660 static bool trans_PROT3W(DisasContext *ctx, arg_rtype *a)
662 TCGv_i64 ax;
664 if (a->rd == 0) {
665 /* nop */
666 return true;
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;
674 ax = tcg_temp_new_i64();
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);
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);
682 tcg_temp_free(ax);
684 return true;