xref: /openbmc/qemu/target/mips/tcg/tx79_translate.c (revision aaaa82a9)
1 /*
2  * Toshiba TX79-specific instructions translation routines
3  *
4  *  Copyright (c) 2018 Fredrik Noring
5  *  Copyright (c) 2021 Philippe Mathieu-Daudé
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
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 /* Include the auto-generated decoder.  */
17 #include "decode-tx79.c.inc"
18 
19 /*
20  *     Overview of the TX79-specific instruction set
21  *     =============================================
22  *
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.
28  *
29  * Reference:
30  *
31  * The Toshiba TX System RISC TX79 Core Architecture manual,
32  * https://wiki.qemu.org/File:C790.pdf
33  */
34 
35 bool 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  *     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)
50  */
51 
52 /*
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
65  */
66 
67 static bool trans_MFHI1(DisasContext *ctx, arg_rtype *a)
68 {
69     gen_store_gpr(cpu_HI[1], a->rd);
70 
71     return true;
72 }
73 
74 static bool trans_MFLO1(DisasContext *ctx, arg_rtype *a)
75 {
76     gen_store_gpr(cpu_LO[1], a->rd);
77 
78     return true;
79 }
80 
81 static bool trans_MTHI1(DisasContext *ctx, arg_rtype *a)
82 {
83     gen_load_gpr(cpu_HI[1], a->rs);
84 
85     return true;
86 }
87 
88 static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a)
89 {
90     gen_load_gpr(cpu_LO[1], a->rs);
91 
92     return true;
93 }
94 
95 /*
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
117  */
118 
119 static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *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         /* nop */
126         return true;
127     }
128 
129     ax = tcg_temp_new_i64();
130     bx = tcg_temp_new_i64();
131 
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);
136 
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);
141 
142     tcg_temp_free(bx);
143     tcg_temp_free(ax);
144 
145     return true;
146 }
147 
148 /* Parallel Subtract Byte */
149 static bool trans_PSUBB(DisasContext *ctx, arg_rtype *a)
150 {
151     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
152 }
153 
154 /* Parallel Subtract Halfword */
155 static bool trans_PSUBH(DisasContext *ctx, arg_rtype *a)
156 {
157     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
158 }
159 
160 /* Parallel Subtract Word */
161 static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a)
162 {
163     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
164 }
165 
166 /*
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
173  */
174 
175 /*
176  *     Absolute (2 instructions)
177  *     -------------------------
178  * PABSH   rd, rt            Parallel Absolute Halfword
179  * PABSW   rd, rt            Parallel Absolute Word
180  */
181 
182 /*
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
189  */
190 
191 /* Parallel And */
192 static bool trans_PAND(DisasContext *ctx, arg_rtype *a)
193 {
194     return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
195 }
196 
197 /* Parallel Or */
198 static bool trans_POR(DisasContext *ctx, arg_rtype *a)
199 {
200     return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
201 }
202 
203 /* Parallel Exclusive Or */
204 static bool trans_PXOR(DisasContext *ctx, arg_rtype *a)
205 {
206     return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
207 }
208 
209 /* Parallel Not Or */
210 static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
211 {
212     return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
213 }
214 
215 /*
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
227  */
228 
229 /*
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
238  */
239 
240 static bool trans_parallel_compare(DisasContext *ctx, arg_rtype *a,
241                                    TCGCond cond, unsigned wlen)
242 {
243     TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
244 
245     if (a->rd == 0) {
246         /* nop */
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     /* 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);
266     }
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);
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 /* Parallel Compare for Greater Than Byte */
289 static bool trans_PCGTB(DisasContext *ctx, arg_rtype *a)
290 {
291     return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
292 }
293 
294 /* Parallel Compare for Equal Byte */
295 static bool trans_PCEQB(DisasContext *ctx, arg_rtype *a)
296 {
297     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
298 }
299 
300 /* Parallel Compare for Greater Than Halfword */
301 static bool trans_PCGTH(DisasContext *ctx, arg_rtype *a)
302 {
303     return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
304 }
305 
306 /* Parallel Compare for Equal Halfword */
307 static bool trans_PCEQH(DisasContext *ctx, arg_rtype *a)
308 {
309     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
310 }
311 
312 /* Parallel Compare for Greater Than Word */
313 static bool trans_PCGTW(DisasContext *ctx, arg_rtype *a)
314 {
315     return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
316 }
317 
318 /* Parallel Compare for Equal Word */
319 static bool trans_PCEQW(DisasContext *ctx, arg_rtype *a)
320 {
321     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
322 }
323 
324 /*
325  *     LZC (1 instruction)
326  *     -------------------
327  * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
328  */
329 
330 /*
331  *     Quadword Load and Store (2 instructions)
332  *     ----------------------------------------
333  * LQ      rt, offset(base)  Load Quadword
334  * SQ      rt, offset(base)  Store Quadword
335  */
336 
337 static bool trans_LQ(DisasContext *ctx, arg_itype *a)
338 {
339     TCGv_i64 t0;
340     TCGv addr;
341 
342     if (a->rt == 0) {
343         /* nop */
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      * Clear least-significant four bits of the effective
353      * address, effectively creating an aligned address.
354      */
355     tcg_gen_andi_tl(addr, addr, ~0xf);
356 
357     /* Lower half */
358     tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
359     gen_store_gpr(t0, a->rt);
360 
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);
365 
366     tcg_temp_free(t0);
367     tcg_temp_free(addr);
368 
369     return true;
370 }
371 
372 /*
373  *     Multiply and Divide (19 instructions)
374  *     -------------------------------------
375  * PMULTW  rd, rs, rt        Parallel Multiply Word
376  * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
377  * PDIVW   rs, rt            Parallel Divide Word
378  * PDIVUW  rs, rt            Parallel Divide Unsigned Word
379  * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
380  * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
381  * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
382  * PMULTH  rd, rs, rt        Parallel Multiply Halfword
383  * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
384  * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
385  * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
386  * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
387  * PDIVBW  rs, rt            Parallel Divide Broadcast Word
388  * PMFHI   rd                Parallel Move From HI Register
389  * PMFLO   rd                Parallel Move From LO Register
390  * PMTHI   rs                Parallel Move To HI Register
391  * PMTLO   rs                Parallel Move To LO Register
392  * PMFHL   rd                Parallel Move From HI/LO Register
393  * PMTHL   rs                Parallel Move To HI/LO Register
394  */
395 
396 /*
397  *     Pack/Extend (11 instructions)
398  *     -----------------------------
399  * PPAC5   rd, rt            Parallel Pack to 5 bits
400  * PPACB   rd, rs, rt        Parallel Pack to Byte
401  * PPACH   rd, rs, rt        Parallel Pack to Halfword
402  * PPACW   rd, rs, rt        Parallel Pack to Word
403  * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
404  * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
405  * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
406  * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
407  * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
408  * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
409  * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
410  */
411 
412 /* Parallel Pack to Word */
413 static bool trans_PPACW(DisasContext *ctx, arg_rtype *a)
414 {
415     TCGv_i64 a0, b0, t0;
416 
417     if (a->rd == 0) {
418         /* nop */
419         return true;
420     }
421 
422     a0 = tcg_temp_new_i64();
423     b0 = tcg_temp_new_i64();
424     t0 = tcg_temp_new_i64();
425 
426     gen_load_gpr(a0, a->rs);
427     gen_load_gpr(b0, a->rt);
428 
429     gen_load_gpr_hi(t0, a->rt); /* b1 */
430     tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
431 
432     gen_load_gpr_hi(t0, a->rs); /* a1 */
433     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
434 
435     tcg_temp_free(t0);
436     tcg_temp_free(b0);
437     tcg_temp_free(a0);
438 
439     return true;
440 }
441 
442 static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
443 {
444     tcg_gen_deposit_i64(dl, b, a, 32, 32);
445     tcg_gen_shri_i64(b, b, 32);
446     tcg_gen_deposit_i64(dh, a, b, 0, 32);
447 }
448 
449 static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
450 {
451     TCGv_i64 ax, bx;
452 
453     if (a->rd == 0) {
454         /* nop */
455         return true;
456     }
457 
458     ax = tcg_temp_new_i64();
459     bx = tcg_temp_new_i64();
460 
461     gen_load_gpr(ax, a->rs);
462     gen_load_gpr(bx, a->rt);
463 
464     /* Lower half */
465     for (int i = 0; i < 64 / (2 * wlen); i++) {
466         tcg_gen_deposit_i64(cpu_gpr[a->rd],
467                             cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
468         tcg_gen_deposit_i64(cpu_gpr[a->rd],
469                             cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
470         tcg_gen_shri_i64(bx, bx, wlen);
471         tcg_gen_shri_i64(ax, ax, wlen);
472     }
473     /* Upper half */
474     for (int i = 0; i < 64 / (2 * wlen); i++) {
475         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
476                             cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
477         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
478                             cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
479         tcg_gen_shri_i64(bx, bx, wlen);
480         tcg_gen_shri_i64(ax, ax, wlen);
481     }
482 
483     tcg_temp_free(bx);
484     tcg_temp_free(ax);
485 
486     return true;
487 }
488 
489 /* Parallel Extend Lower from Byte */
490 static bool trans_PEXTLB(DisasContext *ctx, arg_rtype *a)
491 {
492     return trans_PEXTLx(ctx, a, 8);
493 }
494 
495 /* Parallel Extend Lower from Halfword */
496 static bool trans_PEXTLH(DisasContext *ctx, arg_rtype *a)
497 {
498     return trans_PEXTLx(ctx, a, 16);
499 }
500 
501 /* Parallel Extend Lower from Word */
502 static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
503 {
504     TCGv_i64 ax, bx;
505 
506     if (a->rd == 0) {
507         /* nop */
508         return true;
509     }
510 
511     ax = tcg_temp_new_i64();
512     bx = tcg_temp_new_i64();
513 
514     gen_load_gpr(ax, a->rs);
515     gen_load_gpr(bx, a->rt);
516     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
517 
518     tcg_temp_free(bx);
519     tcg_temp_free(ax);
520 
521     return true;
522 }
523 
524 /* Parallel Extend Upper from Word */
525 static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
526 {
527     TCGv_i64 ax, bx;
528 
529     if (a->rd == 0) {
530         /* nop */
531         return true;
532     }
533 
534     ax = tcg_temp_new_i64();
535     bx = tcg_temp_new_i64();
536 
537     gen_load_gpr_hi(ax, a->rs);
538     gen_load_gpr_hi(bx, a->rt);
539     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
540 
541     tcg_temp_free(bx);
542     tcg_temp_free(ax);
543 
544     return true;
545 }
546 
547 /*
548  *     Others (16 instructions)
549  *     ------------------------
550  * PCPYH   rd, rt            Parallel Copy Halfword
551  * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
552  * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
553  * PREVH   rd, rt            Parallel Reverse Halfword
554  * PINTH   rd, rs, rt        Parallel Interleave Halfword
555  * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
556  * PEXEH   rd, rt            Parallel Exchange Even Halfword
557  * PEXCH   rd, rt            Parallel Exchange Center Halfword
558  * PEXEW   rd, rt            Parallel Exchange Even Word
559  * PEXCW   rd, rt            Parallel Exchange Center Word
560  * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
561  * MFSA    rd                Move from Shift Amount Register
562  * MTSA    rs                Move to Shift Amount Register
563  * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
564  * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
565  * PROT3W  rd, rt            Parallel Rotate 3 Words
566  */
567 
568 /* Parallel Copy Halfword */
569 static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
570 {
571     if (a->rd == 0) {
572         /* nop */
573         return true;
574     }
575 
576     if (a->rt == 0) {
577         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
578         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
579         return true;
580     }
581 
582     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
583     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
584     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
585     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
586 
587     return true;
588 }
589 
590 /* Parallel Copy Lower Doubleword */
591 static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
592 {
593     if (a->rd == 0) {
594         /* nop */
595         return true;
596     }
597 
598     if (a->rs == 0) {
599         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
600     } else {
601         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
602     }
603 
604     if (a->rt == 0) {
605         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
606     } else if (a->rd != a->rt) {
607         tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
608     }
609 
610     return true;
611 }
612 
613 /* Parallel Copy Upper Doubleword */
614 static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
615 {
616     if (a->rd == 0) {
617         /* nop */
618         return true;
619     }
620 
621     gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
622 
623     if (a->rt == 0) {
624         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
625     } else if (a->rd != a->rt) {
626         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
627     }
628 
629     return true;
630 }
631 
632 /* Parallel Rotate 3 Words Left */
633 static bool trans_PROT3W(DisasContext *ctx, arg_rtype *a)
634 {
635     TCGv_i64 ax;
636 
637     if (a->rd == 0) {
638         /* nop */
639         return true;
640     }
641     if (a->rt == 0) {
642         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
643         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
644         return true;
645     }
646 
647     ax = tcg_temp_new_i64();
648 
649     tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
650     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
651 
652     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
653     tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
654 
655     tcg_temp_free(ax);
656 
657     return true;
658 }
659