xref: /openbmc/qemu/target/mips/tcg/tx79_translate.c (revision dce4808f)
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 /*
338  *     Multiply and Divide (19 instructions)
339  *     -------------------------------------
340  * PMULTW  rd, rs, rt        Parallel Multiply Word
341  * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
342  * PDIVW   rs, rt            Parallel Divide Word
343  * PDIVUW  rs, rt            Parallel Divide Unsigned Word
344  * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
345  * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
346  * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
347  * PMULTH  rd, rs, rt        Parallel Multiply Halfword
348  * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
349  * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
350  * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
351  * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
352  * PDIVBW  rs, rt            Parallel Divide Broadcast Word
353  * PMFHI   rd                Parallel Move From HI Register
354  * PMFLO   rd                Parallel Move From LO Register
355  * PMTHI   rs                Parallel Move To HI Register
356  * PMTLO   rs                Parallel Move To LO Register
357  * PMFHL   rd                Parallel Move From HI/LO Register
358  * PMTHL   rs                Parallel Move To HI/LO Register
359  */
360 
361 /*
362  *     Pack/Extend (11 instructions)
363  *     -----------------------------
364  * PPAC5   rd, rt            Parallel Pack to 5 bits
365  * PPACB   rd, rs, rt        Parallel Pack to Byte
366  * PPACH   rd, rs, rt        Parallel Pack to Halfword
367  * PPACW   rd, rs, rt        Parallel Pack to Word
368  * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
369  * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
370  * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
371  * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
372  * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
373  * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
374  * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
375  */
376 
377 /* Parallel Pack to Word */
378 static bool trans_PPACW(DisasContext *ctx, arg_rtype *a)
379 {
380     TCGv_i64 a0, b0, t0;
381 
382     if (a->rd == 0) {
383         /* nop */
384         return true;
385     }
386 
387     a0 = tcg_temp_new_i64();
388     b0 = tcg_temp_new_i64();
389     t0 = tcg_temp_new_i64();
390 
391     gen_load_gpr(a0, a->rs);
392     gen_load_gpr(b0, a->rt);
393 
394     gen_load_gpr_hi(t0, a->rt); /* b1 */
395     tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
396 
397     gen_load_gpr_hi(t0, a->rs); /* a1 */
398     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
399 
400     tcg_temp_free(t0);
401     tcg_temp_free(b0);
402     tcg_temp_free(a0);
403 
404     return true;
405 }
406 
407 static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
408 {
409     tcg_gen_deposit_i64(dl, b, a, 32, 32);
410     tcg_gen_shri_i64(b, b, 32);
411     tcg_gen_deposit_i64(dh, a, b, 0, 32);
412 }
413 
414 static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
415 {
416     TCGv_i64 ax, bx;
417 
418     if (a->rd == 0) {
419         /* nop */
420         return true;
421     }
422 
423     ax = tcg_temp_new_i64();
424     bx = tcg_temp_new_i64();
425 
426     gen_load_gpr(ax, a->rs);
427     gen_load_gpr(bx, a->rt);
428 
429     /* Lower half */
430     for (int i = 0; i < 64 / (2 * wlen); i++) {
431         tcg_gen_deposit_i64(cpu_gpr[a->rd],
432                             cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
433         tcg_gen_deposit_i64(cpu_gpr[a->rd],
434                             cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
435         tcg_gen_shri_i64(bx, bx, wlen);
436         tcg_gen_shri_i64(ax, ax, wlen);
437     }
438     /* Upper half */
439     for (int i = 0; i < 64 / (2 * wlen); i++) {
440         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
441                             cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
442         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
443                             cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
444         tcg_gen_shri_i64(bx, bx, wlen);
445         tcg_gen_shri_i64(ax, ax, wlen);
446     }
447 
448     tcg_temp_free(bx);
449     tcg_temp_free(ax);
450 
451     return true;
452 }
453 
454 /* Parallel Extend Lower from Byte */
455 static bool trans_PEXTLB(DisasContext *ctx, arg_rtype *a)
456 {
457     return trans_PEXTLx(ctx, a, 8);
458 }
459 
460 /* Parallel Extend Lower from Halfword */
461 static bool trans_PEXTLH(DisasContext *ctx, arg_rtype *a)
462 {
463     return trans_PEXTLx(ctx, a, 16);
464 }
465 
466 /* Parallel Extend Lower from Word */
467 static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
468 {
469     TCGv_i64 ax, bx;
470 
471     if (a->rd == 0) {
472         /* nop */
473         return true;
474     }
475 
476     ax = tcg_temp_new_i64();
477     bx = tcg_temp_new_i64();
478 
479     gen_load_gpr(ax, a->rs);
480     gen_load_gpr(bx, a->rt);
481     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
482 
483     tcg_temp_free(bx);
484     tcg_temp_free(ax);
485 
486     return true;
487 }
488 
489 /* Parallel Extend Upper from Word */
490 static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
491 {
492     TCGv_i64 ax, bx;
493 
494     if (a->rd == 0) {
495         /* nop */
496         return true;
497     }
498 
499     ax = tcg_temp_new_i64();
500     bx = tcg_temp_new_i64();
501 
502     gen_load_gpr_hi(ax, a->rs);
503     gen_load_gpr_hi(bx, a->rt);
504     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
505 
506     tcg_temp_free(bx);
507     tcg_temp_free(ax);
508 
509     return true;
510 }
511 
512 /*
513  *     Others (16 instructions)
514  *     ------------------------
515  * PCPYH   rd, rt            Parallel Copy Halfword
516  * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
517  * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
518  * PREVH   rd, rt            Parallel Reverse Halfword
519  * PINTH   rd, rs, rt        Parallel Interleave Halfword
520  * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
521  * PEXEH   rd, rt            Parallel Exchange Even Halfword
522  * PEXCH   rd, rt            Parallel Exchange Center Halfword
523  * PEXEW   rd, rt            Parallel Exchange Even Word
524  * PEXCW   rd, rt            Parallel Exchange Center Word
525  * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
526  * MFSA    rd                Move from Shift Amount Register
527  * MTSA    rs                Move to Shift Amount Register
528  * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
529  * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
530  * PROT3W  rd, rt            Parallel Rotate 3 Words
531  */
532 
533 /* Parallel Copy Halfword */
534 static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
535 {
536     if (a->rd == 0) {
537         /* nop */
538         return true;
539     }
540 
541     if (a->rt == 0) {
542         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
543         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
544         return true;
545     }
546 
547     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
548     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
549     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
550     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
551 
552     return true;
553 }
554 
555 /* Parallel Copy Lower Doubleword */
556 static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
557 {
558     if (a->rd == 0) {
559         /* nop */
560         return true;
561     }
562 
563     if (a->rs == 0) {
564         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
565     } else {
566         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
567     }
568 
569     if (a->rt == 0) {
570         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
571     } else if (a->rd != a->rt) {
572         tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
573     }
574 
575     return true;
576 }
577 
578 /* Parallel Copy Upper Doubleword */
579 static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
580 {
581     if (a->rd == 0) {
582         /* nop */
583         return true;
584     }
585 
586     gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
587 
588     if (a->rt == 0) {
589         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
590     } else if (a->rd != a->rt) {
591         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
592     }
593 
594     return true;
595 }
596 
597 /* Parallel Rotate 3 Words Left */
598 static bool trans_PROT3W(DisasContext *ctx, arg_rtype *a)
599 {
600     TCGv_i64 ax;
601 
602     if (a->rd == 0) {
603         /* nop */
604         return true;
605     }
606     if (a->rt == 0) {
607         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
608         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
609         return true;
610     }
611 
612     ax = tcg_temp_new_i64();
613 
614     tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
615     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
616 
617     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
618     tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
619 
620     tcg_temp_free(ax);
621 
622     return true;
623 }
624