xref: /openbmc/qemu/target/mips/tcg/tx79_translate.c (revision c29e79af)
1a2b0a27dSPhilippe Mathieu-Daudé /*
2a2b0a27dSPhilippe Mathieu-Daudé  * Toshiba TX79-specific instructions translation routines
3a2b0a27dSPhilippe Mathieu-Daudé  *
4a2b0a27dSPhilippe Mathieu-Daudé  *  Copyright (c) 2018 Fredrik Noring
52d4ab117SPhilippe Mathieu-Daudé  *  Copyright (c) 2021 Philippe Mathieu-Daudé
6a2b0a27dSPhilippe Mathieu-Daudé  *
7a2b0a27dSPhilippe Mathieu-Daudé  * SPDX-License-Identifier: GPL-2.0-or-later
8a2b0a27dSPhilippe Mathieu-Daudé  */
9a2b0a27dSPhilippe Mathieu-Daudé 
10a2b0a27dSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
11a2b0a27dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
12709324dcSPhilippe Mathieu-Daudé #include "tcg/tcg-op-gvec.h"
13a2b0a27dSPhilippe Mathieu-Daudé #include "exec/helper-gen.h"
14a2b0a27dSPhilippe Mathieu-Daudé #include "translate.h"
15a2b0a27dSPhilippe Mathieu-Daudé 
16a2b0a27dSPhilippe Mathieu-Daudé /* Include the auto-generated decoder.  */
17a2b0a27dSPhilippe Mathieu-Daudé #include "decode-tx79.c.inc"
18a2b0a27dSPhilippe Mathieu-Daudé 
19a2b0a27dSPhilippe Mathieu-Daudé /*
20a2b0a27dSPhilippe Mathieu-Daudé  *     Overview of the TX79-specific instruction set
21a2b0a27dSPhilippe Mathieu-Daudé  *     =============================================
22a2b0a27dSPhilippe Mathieu-Daudé  *
23a2b0a27dSPhilippe Mathieu-Daudé  * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
24a2b0a27dSPhilippe Mathieu-Daudé  * are only used by the specific quadword (128-bit) LQ/SQ load/store
25a2b0a27dSPhilippe Mathieu-Daudé  * instructions and certain multimedia instructions (MMIs). These MMIs
26a2b0a27dSPhilippe Mathieu-Daudé  * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
27a2b0a27dSPhilippe Mathieu-Daudé  * or sixteen 8-bit paths.
28a2b0a27dSPhilippe Mathieu-Daudé  *
29a2b0a27dSPhilippe Mathieu-Daudé  * Reference:
30a2b0a27dSPhilippe Mathieu-Daudé  *
31a2b0a27dSPhilippe Mathieu-Daudé  * The Toshiba TX System RISC TX79 Core Architecture manual,
32a2b0a27dSPhilippe Mathieu-Daudé  * https://wiki.qemu.org/File:C790.pdf
33a2b0a27dSPhilippe Mathieu-Daudé  */
34a2b0a27dSPhilippe Mathieu-Daudé 
35a2b0a27dSPhilippe Mathieu-Daudé bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
36a2b0a27dSPhilippe Mathieu-Daudé {
37a2b0a27dSPhilippe Mathieu-Daudé     if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
38a2b0a27dSPhilippe Mathieu-Daudé         return true;
39a2b0a27dSPhilippe Mathieu-Daudé     }
40a2b0a27dSPhilippe Mathieu-Daudé     return false;
41a2b0a27dSPhilippe Mathieu-Daudé }
42a2b0a27dSPhilippe Mathieu-Daudé 
43a2b0a27dSPhilippe Mathieu-Daudé /*
44a2b0a27dSPhilippe Mathieu-Daudé  *     Three-Operand Multiply and Multiply-Add (4 instructions)
45a2b0a27dSPhilippe Mathieu-Daudé  *     --------------------------------------------------------
46a2b0a27dSPhilippe Mathieu-Daudé  * MADD    [rd,] rs, rt      Multiply/Add
47a2b0a27dSPhilippe Mathieu-Daudé  * MADDU   [rd,] rs, rt      Multiply/Add Unsigned
48a2b0a27dSPhilippe Mathieu-Daudé  * MULT    [rd,] rs, rt      Multiply (3-operand)
49a2b0a27dSPhilippe Mathieu-Daudé  * MULTU   [rd,] rs, rt      Multiply Unsigned (3-operand)
50a2b0a27dSPhilippe Mathieu-Daudé  */
51a2b0a27dSPhilippe Mathieu-Daudé 
52a2b0a27dSPhilippe Mathieu-Daudé /*
53a2b0a27dSPhilippe Mathieu-Daudé  *     Multiply Instructions for Pipeline 1 (10 instructions)
54a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------------------------------------
55a2b0a27dSPhilippe Mathieu-Daudé  * MULT1   [rd,] rs, rt      Multiply Pipeline 1
56a2b0a27dSPhilippe Mathieu-Daudé  * MULTU1  [rd,] rs, rt      Multiply Unsigned Pipeline 1
57a2b0a27dSPhilippe Mathieu-Daudé  * DIV1    rs, rt            Divide Pipeline 1
58a2b0a27dSPhilippe Mathieu-Daudé  * DIVU1   rs, rt            Divide Unsigned Pipeline 1
59a2b0a27dSPhilippe Mathieu-Daudé  * MADD1   [rd,] rs, rt      Multiply-Add Pipeline 1
60a2b0a27dSPhilippe Mathieu-Daudé  * MADDU1  [rd,] rs, rt      Multiply-Add Unsigned Pipeline 1
61a2b0a27dSPhilippe Mathieu-Daudé  * MFHI1   rd                Move From HI1 Register
62a2b0a27dSPhilippe Mathieu-Daudé  * MFLO1   rd                Move From LO1 Register
63a2b0a27dSPhilippe Mathieu-Daudé  * MTHI1   rs                Move To HI1 Register
64a2b0a27dSPhilippe Mathieu-Daudé  * MTLO1   rs                Move To LO1 Register
65a2b0a27dSPhilippe Mathieu-Daudé  */
66a2b0a27dSPhilippe Mathieu-Daudé 
6734fe9fa3SPhilippe Mathieu-Daudé static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
68a2b0a27dSPhilippe Mathieu-Daudé {
69a2b0a27dSPhilippe Mathieu-Daudé     gen_store_gpr(cpu_HI[1], a->rd);
70a2b0a27dSPhilippe Mathieu-Daudé 
71a2b0a27dSPhilippe Mathieu-Daudé     return true;
72a2b0a27dSPhilippe Mathieu-Daudé }
73a2b0a27dSPhilippe Mathieu-Daudé 
7434fe9fa3SPhilippe Mathieu-Daudé static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
75a2b0a27dSPhilippe Mathieu-Daudé {
76a2b0a27dSPhilippe Mathieu-Daudé     gen_store_gpr(cpu_LO[1], a->rd);
77a2b0a27dSPhilippe Mathieu-Daudé 
78a2b0a27dSPhilippe Mathieu-Daudé     return true;
79a2b0a27dSPhilippe Mathieu-Daudé }
80a2b0a27dSPhilippe Mathieu-Daudé 
8134fe9fa3SPhilippe Mathieu-Daudé static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
82a2b0a27dSPhilippe Mathieu-Daudé {
83a2b0a27dSPhilippe Mathieu-Daudé     gen_load_gpr(cpu_HI[1], a->rs);
84a2b0a27dSPhilippe Mathieu-Daudé 
85a2b0a27dSPhilippe Mathieu-Daudé     return true;
86a2b0a27dSPhilippe Mathieu-Daudé }
87a2b0a27dSPhilippe Mathieu-Daudé 
8834fe9fa3SPhilippe Mathieu-Daudé static bool trans_MTLO1(DisasContext *ctx, arg_r *a)
89a2b0a27dSPhilippe Mathieu-Daudé {
90a2b0a27dSPhilippe Mathieu-Daudé     gen_load_gpr(cpu_LO[1], a->rs);
91a2b0a27dSPhilippe Mathieu-Daudé 
92a2b0a27dSPhilippe Mathieu-Daudé     return true;
93a2b0a27dSPhilippe Mathieu-Daudé }
94a2b0a27dSPhilippe Mathieu-Daudé 
95a2b0a27dSPhilippe Mathieu-Daudé /*
96a2b0a27dSPhilippe Mathieu-Daudé  *     Arithmetic (19 instructions)
97a2b0a27dSPhilippe Mathieu-Daudé  *     ----------------------------
98a2b0a27dSPhilippe Mathieu-Daudé  * PADDB   rd, rs, rt        Parallel Add Byte
99a2b0a27dSPhilippe Mathieu-Daudé  * PSUBB   rd, rs, rt        Parallel Subtract Byte
100a2b0a27dSPhilippe Mathieu-Daudé  * PADDH   rd, rs, rt        Parallel Add Halfword
101a2b0a27dSPhilippe Mathieu-Daudé  * PSUBH   rd, rs, rt        Parallel Subtract Halfword
102a2b0a27dSPhilippe Mathieu-Daudé  * PADDW   rd, rs, rt        Parallel Add Word
103a2b0a27dSPhilippe Mathieu-Daudé  * PSUBW   rd, rs, rt        Parallel Subtract Word
104a2b0a27dSPhilippe Mathieu-Daudé  * PADSBH  rd, rs, rt        Parallel Add/Subtract Halfword
105a2b0a27dSPhilippe Mathieu-Daudé  * PADDSB  rd, rs, rt        Parallel Add with Signed Saturation Byte
106a2b0a27dSPhilippe Mathieu-Daudé  * PSUBSB  rd, rs, rt        Parallel Subtract with Signed Saturation Byte
107a2b0a27dSPhilippe Mathieu-Daudé  * PADDSH  rd, rs, rt        Parallel Add with Signed Saturation Halfword
108a2b0a27dSPhilippe Mathieu-Daudé  * PSUBSH  rd, rs, rt        Parallel Subtract with Signed Saturation Halfword
109a2b0a27dSPhilippe Mathieu-Daudé  * PADDSW  rd, rs, rt        Parallel Add with Signed Saturation Word
110a2b0a27dSPhilippe Mathieu-Daudé  * PSUBSW  rd, rs, rt        Parallel Subtract with Signed Saturation Word
111a2b0a27dSPhilippe Mathieu-Daudé  * PADDUB  rd, rs, rt        Parallel Add with Unsigned saturation Byte
112a2b0a27dSPhilippe Mathieu-Daudé  * PSUBUB  rd, rs, rt        Parallel Subtract with Unsigned saturation Byte
113a2b0a27dSPhilippe Mathieu-Daudé  * PADDUH  rd, rs, rt        Parallel Add with Unsigned saturation Halfword
114a2b0a27dSPhilippe Mathieu-Daudé  * PSUBUH  rd, rs, rt        Parallel Subtract with Unsigned saturation Halfword
115a2b0a27dSPhilippe Mathieu-Daudé  * PADDUW  rd, rs, rt        Parallel Add with Unsigned saturation Word
116a2b0a27dSPhilippe Mathieu-Daudé  * PSUBUW  rd, rs, rt        Parallel Subtract with Unsigned saturation Word
117a2b0a27dSPhilippe Mathieu-Daudé  */
118a2b0a27dSPhilippe Mathieu-Daudé 
11934fe9fa3SPhilippe Mathieu-Daudé static bool trans_parallel_arith(DisasContext *ctx, arg_r *a,
1202d4ab117SPhilippe Mathieu-Daudé                                  void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
1212d4ab117SPhilippe Mathieu-Daudé {
1222d4ab117SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
1232d4ab117SPhilippe Mathieu-Daudé 
1242d4ab117SPhilippe Mathieu-Daudé     if (a->rd == 0) {
1252d4ab117SPhilippe Mathieu-Daudé         /* nop */
1262d4ab117SPhilippe Mathieu-Daudé         return true;
1272d4ab117SPhilippe Mathieu-Daudé     }
1282d4ab117SPhilippe Mathieu-Daudé 
1292d4ab117SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
1302d4ab117SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
1312d4ab117SPhilippe Mathieu-Daudé 
1322d4ab117SPhilippe Mathieu-Daudé     /* Lower half */
1332d4ab117SPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
1342d4ab117SPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
1352d4ab117SPhilippe Mathieu-Daudé     gen_logic_i64(cpu_gpr[a->rd], ax, bx);
1362d4ab117SPhilippe Mathieu-Daudé 
1372d4ab117SPhilippe Mathieu-Daudé     /* Upper half */
1382d4ab117SPhilippe Mathieu-Daudé     gen_load_gpr_hi(ax, a->rs);
1392d4ab117SPhilippe Mathieu-Daudé     gen_load_gpr_hi(bx, a->rt);
1402d4ab117SPhilippe Mathieu-Daudé     gen_logic_i64(cpu_gpr_hi[a->rd], ax, bx);
1412d4ab117SPhilippe Mathieu-Daudé     return true;
1422d4ab117SPhilippe Mathieu-Daudé }
1432d4ab117SPhilippe Mathieu-Daudé 
144709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Byte */
14534fe9fa3SPhilippe Mathieu-Daudé static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
146709324dcSPhilippe Mathieu-Daudé {
147709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
148709324dcSPhilippe Mathieu-Daudé }
149709324dcSPhilippe Mathieu-Daudé 
150709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Halfword */
15134fe9fa3SPhilippe Mathieu-Daudé static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
152709324dcSPhilippe Mathieu-Daudé {
153709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
154709324dcSPhilippe Mathieu-Daudé }
155709324dcSPhilippe Mathieu-Daudé 
156709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Word */
15734fe9fa3SPhilippe Mathieu-Daudé static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
158709324dcSPhilippe Mathieu-Daudé {
159709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
160709324dcSPhilippe Mathieu-Daudé }
161709324dcSPhilippe Mathieu-Daudé 
162a2b0a27dSPhilippe Mathieu-Daudé /*
163a2b0a27dSPhilippe Mathieu-Daudé  *     Min/Max (4 instructions)
164a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
165a2b0a27dSPhilippe Mathieu-Daudé  * PMAXH   rd, rs, rt        Parallel Maximum Halfword
166a2b0a27dSPhilippe Mathieu-Daudé  * PMINH   rd, rs, rt        Parallel Minimum Halfword
167a2b0a27dSPhilippe Mathieu-Daudé  * PMAXW   rd, rs, rt        Parallel Maximum Word
168a2b0a27dSPhilippe Mathieu-Daudé  * PMINW   rd, rs, rt        Parallel Minimum Word
169a2b0a27dSPhilippe Mathieu-Daudé  */
170a2b0a27dSPhilippe Mathieu-Daudé 
171a2b0a27dSPhilippe Mathieu-Daudé /*
172a2b0a27dSPhilippe Mathieu-Daudé  *     Absolute (2 instructions)
173a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------------
174a2b0a27dSPhilippe Mathieu-Daudé  * PABSH   rd, rt            Parallel Absolute Halfword
175a2b0a27dSPhilippe Mathieu-Daudé  * PABSW   rd, rt            Parallel Absolute Word
176a2b0a27dSPhilippe Mathieu-Daudé  */
177a2b0a27dSPhilippe Mathieu-Daudé 
178a2b0a27dSPhilippe Mathieu-Daudé /*
179a2b0a27dSPhilippe Mathieu-Daudé  *     Logical (4 instructions)
180a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
181a2b0a27dSPhilippe Mathieu-Daudé  * PAND    rd, rs, rt        Parallel AND
182a2b0a27dSPhilippe Mathieu-Daudé  * POR     rd, rs, rt        Parallel OR
183a2b0a27dSPhilippe Mathieu-Daudé  * PXOR    rd, rs, rt        Parallel XOR
184a2b0a27dSPhilippe Mathieu-Daudé  * PNOR    rd, rs, rt        Parallel NOR
185a2b0a27dSPhilippe Mathieu-Daudé  */
186a2b0a27dSPhilippe Mathieu-Daudé 
1872d4ab117SPhilippe Mathieu-Daudé /* Parallel And */
18834fe9fa3SPhilippe Mathieu-Daudé static bool trans_PAND(DisasContext *ctx, arg_r *a)
1892d4ab117SPhilippe Mathieu-Daudé {
1902d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
1912d4ab117SPhilippe Mathieu-Daudé }
1922d4ab117SPhilippe Mathieu-Daudé 
1932d4ab117SPhilippe Mathieu-Daudé /* Parallel Or */
19434fe9fa3SPhilippe Mathieu-Daudé static bool trans_POR(DisasContext *ctx, arg_r *a)
1952d4ab117SPhilippe Mathieu-Daudé {
1962d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
1972d4ab117SPhilippe Mathieu-Daudé }
1982d4ab117SPhilippe Mathieu-Daudé 
1992d4ab117SPhilippe Mathieu-Daudé /* Parallel Exclusive Or */
20034fe9fa3SPhilippe Mathieu-Daudé static bool trans_PXOR(DisasContext *ctx, arg_r *a)
2012d4ab117SPhilippe Mathieu-Daudé {
2022d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
2032d4ab117SPhilippe Mathieu-Daudé }
2042d4ab117SPhilippe Mathieu-Daudé 
2052d4ab117SPhilippe Mathieu-Daudé /* Parallel Not Or */
20634fe9fa3SPhilippe Mathieu-Daudé static bool trans_PNOR(DisasContext *ctx, arg_r *a)
2072d4ab117SPhilippe Mathieu-Daudé {
2082d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
2092d4ab117SPhilippe Mathieu-Daudé }
2102d4ab117SPhilippe Mathieu-Daudé 
211a2b0a27dSPhilippe Mathieu-Daudé /*
212a2b0a27dSPhilippe Mathieu-Daudé  *     Shift (9 instructions)
213a2b0a27dSPhilippe Mathieu-Daudé  *     ----------------------
214a2b0a27dSPhilippe Mathieu-Daudé  * PSLLH   rd, rt, sa        Parallel Shift Left Logical Halfword
215a2b0a27dSPhilippe Mathieu-Daudé  * PSRLH   rd, rt, sa        Parallel Shift Right Logical Halfword
216a2b0a27dSPhilippe Mathieu-Daudé  * PSRAH   rd, rt, sa        Parallel Shift Right Arithmetic Halfword
217a2b0a27dSPhilippe Mathieu-Daudé  * PSLLW   rd, rt, sa        Parallel Shift Left Logical Word
218a2b0a27dSPhilippe Mathieu-Daudé  * PSRLW   rd, rt, sa        Parallel Shift Right Logical Word
219a2b0a27dSPhilippe Mathieu-Daudé  * PSRAW   rd, rt, sa        Parallel Shift Right Arithmetic Word
220a2b0a27dSPhilippe Mathieu-Daudé  * PSLLVW  rd, rt, rs        Parallel Shift Left Logical Variable Word
221a2b0a27dSPhilippe Mathieu-Daudé  * PSRLVW  rd, rt, rs        Parallel Shift Right Logical Variable Word
222a2b0a27dSPhilippe Mathieu-Daudé  * PSRAVW  rd, rt, rs        Parallel Shift Right Arithmetic Variable Word
223a2b0a27dSPhilippe Mathieu-Daudé  */
224a2b0a27dSPhilippe Mathieu-Daudé 
225a2b0a27dSPhilippe Mathieu-Daudé /*
226a2b0a27dSPhilippe Mathieu-Daudé  *     Compare (6 instructions)
227a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
228a2b0a27dSPhilippe Mathieu-Daudé  * PCGTB   rd, rs, rt        Parallel Compare for Greater Than Byte
229a2b0a27dSPhilippe Mathieu-Daudé  * PCEQB   rd, rs, rt        Parallel Compare for Equal Byte
230a2b0a27dSPhilippe Mathieu-Daudé  * PCGTH   rd, rs, rt        Parallel Compare for Greater Than Halfword
231a2b0a27dSPhilippe Mathieu-Daudé  * PCEQH   rd, rs, rt        Parallel Compare for Equal Halfword
232a2b0a27dSPhilippe Mathieu-Daudé  * PCGTW   rd, rs, rt        Parallel Compare for Greater Than Word
233a2b0a27dSPhilippe Mathieu-Daudé  * PCEQW   rd, rs, rt        Parallel Compare for Equal Word
234a2b0a27dSPhilippe Mathieu-Daudé  */
235a2b0a27dSPhilippe Mathieu-Daudé 
23634fe9fa3SPhilippe Mathieu-Daudé static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
23782fbf9fcSPhilippe Mathieu-Daudé                                    TCGCond cond, unsigned wlen)
23882fbf9fcSPhilippe Mathieu-Daudé {
23982fbf9fcSPhilippe Mathieu-Daudé     TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
24082fbf9fcSPhilippe Mathieu-Daudé 
24182fbf9fcSPhilippe Mathieu-Daudé     if (a->rd == 0) {
24282fbf9fcSPhilippe Mathieu-Daudé         /* nop */
24382fbf9fcSPhilippe Mathieu-Daudé         return true;
24482fbf9fcSPhilippe Mathieu-Daudé     }
24582fbf9fcSPhilippe Mathieu-Daudé 
246*c29e79afSRichard Henderson     c0 = tcg_constant_tl(0);
247*c29e79afSRichard Henderson     c1 = tcg_constant_tl(0xffffffff);
24882fbf9fcSPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
24982fbf9fcSPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
25082fbf9fcSPhilippe Mathieu-Daudé     t0 = tcg_temp_new_i64();
25182fbf9fcSPhilippe Mathieu-Daudé     t1 = tcg_temp_new_i64();
25282fbf9fcSPhilippe Mathieu-Daudé     t2 = tcg_temp_new_i64();
25382fbf9fcSPhilippe Mathieu-Daudé 
25482fbf9fcSPhilippe Mathieu-Daudé     /* Lower half */
25582fbf9fcSPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
25682fbf9fcSPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
25782fbf9fcSPhilippe Mathieu-Daudé     for (int i = 0; i < (64 / wlen); i++) {
25882fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
25982fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
26082fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
26182fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
26282fbf9fcSPhilippe Mathieu-Daudé     }
26382fbf9fcSPhilippe Mathieu-Daudé     /* Upper half */
26482fbf9fcSPhilippe Mathieu-Daudé     gen_load_gpr_hi(ax, a->rs);
26582fbf9fcSPhilippe Mathieu-Daudé     gen_load_gpr_hi(bx, a->rt);
26682fbf9fcSPhilippe Mathieu-Daudé     for (int i = 0; i < (64 / wlen); i++) {
26782fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
26882fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
26982fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
27082fbf9fcSPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
27182fbf9fcSPhilippe Mathieu-Daudé     }
27282fbf9fcSPhilippe Mathieu-Daudé     return true;
27382fbf9fcSPhilippe Mathieu-Daudé }
27482fbf9fcSPhilippe Mathieu-Daudé 
2758bd42c00SPhilippe Mathieu-Daudé /* Parallel Compare for Greater Than Byte */
27634fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
2778bd42c00SPhilippe Mathieu-Daudé {
2788bd42c00SPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
2798bd42c00SPhilippe Mathieu-Daudé }
2808bd42c00SPhilippe Mathieu-Daudé 
28182fbf9fcSPhilippe Mathieu-Daudé /* Parallel Compare for Equal Byte */
28234fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
28382fbf9fcSPhilippe Mathieu-Daudé {
28482fbf9fcSPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
28582fbf9fcSPhilippe Mathieu-Daudé }
28682fbf9fcSPhilippe Mathieu-Daudé 
2878bd42c00SPhilippe Mathieu-Daudé /* Parallel Compare for Greater Than Halfword */
28834fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
2898bd42c00SPhilippe Mathieu-Daudé {
2908bd42c00SPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
2918bd42c00SPhilippe Mathieu-Daudé }
2928bd42c00SPhilippe Mathieu-Daudé 
29382fbf9fcSPhilippe Mathieu-Daudé /* Parallel Compare for Equal Halfword */
29434fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
29582fbf9fcSPhilippe Mathieu-Daudé {
29682fbf9fcSPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
29782fbf9fcSPhilippe Mathieu-Daudé }
29882fbf9fcSPhilippe Mathieu-Daudé 
2998bd42c00SPhilippe Mathieu-Daudé /* Parallel Compare for Greater Than Word */
30034fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
3018bd42c00SPhilippe Mathieu-Daudé {
3028bd42c00SPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
3038bd42c00SPhilippe Mathieu-Daudé }
3048bd42c00SPhilippe Mathieu-Daudé 
30582fbf9fcSPhilippe Mathieu-Daudé /* Parallel Compare for Equal Word */
30634fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
30782fbf9fcSPhilippe Mathieu-Daudé {
30882fbf9fcSPhilippe Mathieu-Daudé     return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
30982fbf9fcSPhilippe Mathieu-Daudé }
31082fbf9fcSPhilippe Mathieu-Daudé 
311a2b0a27dSPhilippe Mathieu-Daudé /*
312a2b0a27dSPhilippe Mathieu-Daudé  *     LZC (1 instruction)
313a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------
314a2b0a27dSPhilippe Mathieu-Daudé  * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
315a2b0a27dSPhilippe Mathieu-Daudé  */
316a2b0a27dSPhilippe Mathieu-Daudé 
317a2b0a27dSPhilippe Mathieu-Daudé /*
318a2b0a27dSPhilippe Mathieu-Daudé  *     Quadword Load and Store (2 instructions)
319a2b0a27dSPhilippe Mathieu-Daudé  *     ----------------------------------------
320a2b0a27dSPhilippe Mathieu-Daudé  * LQ      rt, offset(base)  Load Quadword
321a2b0a27dSPhilippe Mathieu-Daudé  * SQ      rt, offset(base)  Store Quadword
322a2b0a27dSPhilippe Mathieu-Daudé  */
323a2b0a27dSPhilippe Mathieu-Daudé 
32434fe9fa3SPhilippe Mathieu-Daudé static bool trans_LQ(DisasContext *ctx, arg_i *a)
325aaaa82a9SPhilippe Mathieu-Daudé {
326aaaa82a9SPhilippe Mathieu-Daudé     TCGv_i64 t0;
327aaaa82a9SPhilippe Mathieu-Daudé     TCGv addr;
328aaaa82a9SPhilippe Mathieu-Daudé 
329aaaa82a9SPhilippe Mathieu-Daudé     if (a->rt == 0) {
330aaaa82a9SPhilippe Mathieu-Daudé         /* nop */
331aaaa82a9SPhilippe Mathieu-Daudé         return true;
332aaaa82a9SPhilippe Mathieu-Daudé     }
333aaaa82a9SPhilippe Mathieu-Daudé 
334aaaa82a9SPhilippe Mathieu-Daudé     t0 = tcg_temp_new_i64();
335aaaa82a9SPhilippe Mathieu-Daudé     addr = tcg_temp_new();
336aaaa82a9SPhilippe Mathieu-Daudé 
337aaaa82a9SPhilippe Mathieu-Daudé     gen_base_offset_addr(ctx, addr, a->base, a->offset);
338aaaa82a9SPhilippe Mathieu-Daudé     /*
339aaaa82a9SPhilippe Mathieu-Daudé      * Clear least-significant four bits of the effective
340aaaa82a9SPhilippe Mathieu-Daudé      * address, effectively creating an aligned address.
341aaaa82a9SPhilippe Mathieu-Daudé      */
342aaaa82a9SPhilippe Mathieu-Daudé     tcg_gen_andi_tl(addr, addr, ~0xf);
343aaaa82a9SPhilippe Mathieu-Daudé 
344aaaa82a9SPhilippe Mathieu-Daudé     /* Lower half */
345fc313c64SFrédéric Pétrot     tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
346aaaa82a9SPhilippe Mathieu-Daudé     gen_store_gpr(t0, a->rt);
347aaaa82a9SPhilippe Mathieu-Daudé 
348aaaa82a9SPhilippe Mathieu-Daudé     /* Upper half */
349aaaa82a9SPhilippe Mathieu-Daudé     tcg_gen_addi_i64(addr, addr, 8);
350fc313c64SFrédéric Pétrot     tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
351aaaa82a9SPhilippe Mathieu-Daudé     gen_store_gpr_hi(t0, a->rt);
352aaaa82a9SPhilippe Mathieu-Daudé     return true;
353aaaa82a9SPhilippe Mathieu-Daudé }
354aaaa82a9SPhilippe Mathieu-Daudé 
35534fe9fa3SPhilippe Mathieu-Daudé static bool trans_SQ(DisasContext *ctx, arg_i *a)
35680ad6303SPhilippe Mathieu-Daudé {
35780ad6303SPhilippe Mathieu-Daudé     TCGv_i64 t0 = tcg_temp_new_i64();
35880ad6303SPhilippe Mathieu-Daudé     TCGv addr = tcg_temp_new();
35980ad6303SPhilippe Mathieu-Daudé 
36080ad6303SPhilippe Mathieu-Daudé     gen_base_offset_addr(ctx, addr, a->base, a->offset);
36180ad6303SPhilippe Mathieu-Daudé     /*
36280ad6303SPhilippe Mathieu-Daudé      * Clear least-significant four bits of the effective
36380ad6303SPhilippe Mathieu-Daudé      * address, effectively creating an aligned address.
36480ad6303SPhilippe Mathieu-Daudé      */
36580ad6303SPhilippe Mathieu-Daudé     tcg_gen_andi_tl(addr, addr, ~0xf);
36680ad6303SPhilippe Mathieu-Daudé 
36780ad6303SPhilippe Mathieu-Daudé     /* Lower half */
36880ad6303SPhilippe Mathieu-Daudé     gen_load_gpr(t0, a->rt);
369fc313c64SFrédéric Pétrot     tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
37080ad6303SPhilippe Mathieu-Daudé 
37180ad6303SPhilippe Mathieu-Daudé     /* Upper half */
37280ad6303SPhilippe Mathieu-Daudé     tcg_gen_addi_i64(addr, addr, 8);
37380ad6303SPhilippe Mathieu-Daudé     gen_load_gpr_hi(t0, a->rt);
374fc313c64SFrédéric Pétrot     tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
37580ad6303SPhilippe Mathieu-Daudé     return true;
37680ad6303SPhilippe Mathieu-Daudé }
37780ad6303SPhilippe Mathieu-Daudé 
378a2b0a27dSPhilippe Mathieu-Daudé /*
379a2b0a27dSPhilippe Mathieu-Daudé  *     Multiply and Divide (19 instructions)
380a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------------------------
381a2b0a27dSPhilippe Mathieu-Daudé  * PMULTW  rd, rs, rt        Parallel Multiply Word
382a2b0a27dSPhilippe Mathieu-Daudé  * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
383a2b0a27dSPhilippe Mathieu-Daudé  * PDIVW   rs, rt            Parallel Divide Word
384a2b0a27dSPhilippe Mathieu-Daudé  * PDIVUW  rs, rt            Parallel Divide Unsigned Word
385a2b0a27dSPhilippe Mathieu-Daudé  * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
386a2b0a27dSPhilippe Mathieu-Daudé  * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
387a2b0a27dSPhilippe Mathieu-Daudé  * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
388a2b0a27dSPhilippe Mathieu-Daudé  * PMULTH  rd, rs, rt        Parallel Multiply Halfword
389a2b0a27dSPhilippe Mathieu-Daudé  * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
390a2b0a27dSPhilippe Mathieu-Daudé  * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
391a2b0a27dSPhilippe Mathieu-Daudé  * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
392a2b0a27dSPhilippe Mathieu-Daudé  * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
393a2b0a27dSPhilippe Mathieu-Daudé  * PDIVBW  rs, rt            Parallel Divide Broadcast Word
394a2b0a27dSPhilippe Mathieu-Daudé  * PMFHI   rd                Parallel Move From HI Register
395a2b0a27dSPhilippe Mathieu-Daudé  * PMFLO   rd                Parallel Move From LO Register
396a2b0a27dSPhilippe Mathieu-Daudé  * PMTHI   rs                Parallel Move To HI Register
397a2b0a27dSPhilippe Mathieu-Daudé  * PMTLO   rs                Parallel Move To LO Register
398a2b0a27dSPhilippe Mathieu-Daudé  * PMFHL   rd                Parallel Move From HI/LO Register
399a2b0a27dSPhilippe Mathieu-Daudé  * PMTHL   rs                Parallel Move To HI/LO Register
400a2b0a27dSPhilippe Mathieu-Daudé  */
401a2b0a27dSPhilippe Mathieu-Daudé 
402a2b0a27dSPhilippe Mathieu-Daudé /*
403a2b0a27dSPhilippe Mathieu-Daudé  *     Pack/Extend (11 instructions)
404a2b0a27dSPhilippe Mathieu-Daudé  *     -----------------------------
405a2b0a27dSPhilippe Mathieu-Daudé  * PPAC5   rd, rt            Parallel Pack to 5 bits
406a2b0a27dSPhilippe Mathieu-Daudé  * PPACB   rd, rs, rt        Parallel Pack to Byte
407a2b0a27dSPhilippe Mathieu-Daudé  * PPACH   rd, rs, rt        Parallel Pack to Halfword
408a2b0a27dSPhilippe Mathieu-Daudé  * PPACW   rd, rs, rt        Parallel Pack to Word
409a2b0a27dSPhilippe Mathieu-Daudé  * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
410a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
411a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
412a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
413a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
414a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
415a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
416a2b0a27dSPhilippe Mathieu-Daudé  */
417a2b0a27dSPhilippe Mathieu-Daudé 
41871c49f39SPhilippe Mathieu-Daudé /* Parallel Pack to Word */
41934fe9fa3SPhilippe Mathieu-Daudé static bool trans_PPACW(DisasContext *ctx, arg_r *a)
42071c49f39SPhilippe Mathieu-Daudé {
42171c49f39SPhilippe Mathieu-Daudé     TCGv_i64 a0, b0, t0;
42271c49f39SPhilippe Mathieu-Daudé 
42371c49f39SPhilippe Mathieu-Daudé     if (a->rd == 0) {
42471c49f39SPhilippe Mathieu-Daudé         /* nop */
42571c49f39SPhilippe Mathieu-Daudé         return true;
42671c49f39SPhilippe Mathieu-Daudé     }
42771c49f39SPhilippe Mathieu-Daudé 
42871c49f39SPhilippe Mathieu-Daudé     a0 = tcg_temp_new_i64();
42971c49f39SPhilippe Mathieu-Daudé     b0 = tcg_temp_new_i64();
43071c49f39SPhilippe Mathieu-Daudé     t0 = tcg_temp_new_i64();
43171c49f39SPhilippe Mathieu-Daudé 
43271c49f39SPhilippe Mathieu-Daudé     gen_load_gpr(a0, a->rs);
43371c49f39SPhilippe Mathieu-Daudé     gen_load_gpr(b0, a->rt);
43471c49f39SPhilippe Mathieu-Daudé 
43571c49f39SPhilippe Mathieu-Daudé     gen_load_gpr_hi(t0, a->rt); /* b1 */
43671c49f39SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
43771c49f39SPhilippe Mathieu-Daudé 
43871c49f39SPhilippe Mathieu-Daudé     gen_load_gpr_hi(t0, a->rs); /* a1 */
43971c49f39SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
44071c49f39SPhilippe Mathieu-Daudé     return true;
44171c49f39SPhilippe Mathieu-Daudé }
44271c49f39SPhilippe Mathieu-Daudé 
4430bc69372SPhilippe Mathieu-Daudé static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
4440bc69372SPhilippe Mathieu-Daudé {
4450bc69372SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(dl, b, a, 32, 32);
4460bc69372SPhilippe Mathieu-Daudé     tcg_gen_shri_i64(b, b, 32);
4470bc69372SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(dh, a, b, 0, 32);
4480bc69372SPhilippe Mathieu-Daudé }
4490bc69372SPhilippe Mathieu-Daudé 
45034fe9fa3SPhilippe Mathieu-Daudé static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
451a9ea77f2SPhilippe Mathieu-Daudé {
452a9ea77f2SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
453a9ea77f2SPhilippe Mathieu-Daudé 
454a9ea77f2SPhilippe Mathieu-Daudé     if (a->rd == 0) {
455a9ea77f2SPhilippe Mathieu-Daudé         /* nop */
456a9ea77f2SPhilippe Mathieu-Daudé         return true;
457a9ea77f2SPhilippe Mathieu-Daudé     }
458a9ea77f2SPhilippe Mathieu-Daudé 
459a9ea77f2SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
460a9ea77f2SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
461a9ea77f2SPhilippe Mathieu-Daudé 
462a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
463a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
464a9ea77f2SPhilippe Mathieu-Daudé 
465a9ea77f2SPhilippe Mathieu-Daudé     /* Lower half */
466a9ea77f2SPhilippe Mathieu-Daudé     for (int i = 0; i < 64 / (2 * wlen); i++) {
467a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr[a->rd],
468a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
469a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr[a->rd],
470a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
471a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(bx, bx, wlen);
472a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(ax, ax, wlen);
473a9ea77f2SPhilippe Mathieu-Daudé     }
474a9ea77f2SPhilippe Mathieu-Daudé     /* Upper half */
475a9ea77f2SPhilippe Mathieu-Daudé     for (int i = 0; i < 64 / (2 * wlen); i++) {
476a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
477a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
478a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
479a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
480a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(bx, bx, wlen);
481a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(ax, ax, wlen);
482a9ea77f2SPhilippe Mathieu-Daudé     }
483a9ea77f2SPhilippe Mathieu-Daudé     return true;
484a9ea77f2SPhilippe Mathieu-Daudé }
485a9ea77f2SPhilippe Mathieu-Daudé 
486a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Byte */
48734fe9fa3SPhilippe Mathieu-Daudé static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
488a9ea77f2SPhilippe Mathieu-Daudé {
489a9ea77f2SPhilippe Mathieu-Daudé     return trans_PEXTLx(ctx, a, 8);
490a9ea77f2SPhilippe Mathieu-Daudé }
491a9ea77f2SPhilippe Mathieu-Daudé 
492a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Halfword */
49334fe9fa3SPhilippe Mathieu-Daudé static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
494a9ea77f2SPhilippe Mathieu-Daudé {
495a9ea77f2SPhilippe Mathieu-Daudé     return trans_PEXTLx(ctx, a, 16);
496a9ea77f2SPhilippe Mathieu-Daudé }
497a9ea77f2SPhilippe Mathieu-Daudé 
498a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Word */
49934fe9fa3SPhilippe Mathieu-Daudé static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
500a9ea77f2SPhilippe Mathieu-Daudé {
501a9ea77f2SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
502a9ea77f2SPhilippe Mathieu-Daudé 
503a9ea77f2SPhilippe Mathieu-Daudé     if (a->rd == 0) {
504a9ea77f2SPhilippe Mathieu-Daudé         /* nop */
505a9ea77f2SPhilippe Mathieu-Daudé         return true;
506a9ea77f2SPhilippe Mathieu-Daudé     }
507a9ea77f2SPhilippe Mathieu-Daudé 
508a9ea77f2SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
509a9ea77f2SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
510a9ea77f2SPhilippe Mathieu-Daudé 
511a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
512a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
513a9ea77f2SPhilippe Mathieu-Daudé     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
514a9ea77f2SPhilippe Mathieu-Daudé     return true;
515a9ea77f2SPhilippe Mathieu-Daudé }
516a9ea77f2SPhilippe Mathieu-Daudé 
5170bc69372SPhilippe Mathieu-Daudé /* Parallel Extend Upper from Word */
51834fe9fa3SPhilippe Mathieu-Daudé static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
5190bc69372SPhilippe Mathieu-Daudé {
5200bc69372SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
5210bc69372SPhilippe Mathieu-Daudé 
5220bc69372SPhilippe Mathieu-Daudé     if (a->rd == 0) {
5230bc69372SPhilippe Mathieu-Daudé         /* nop */
5240bc69372SPhilippe Mathieu-Daudé         return true;
5250bc69372SPhilippe Mathieu-Daudé     }
5260bc69372SPhilippe Mathieu-Daudé 
5270bc69372SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
5280bc69372SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
5290bc69372SPhilippe Mathieu-Daudé 
5300bc69372SPhilippe Mathieu-Daudé     gen_load_gpr_hi(ax, a->rs);
5310bc69372SPhilippe Mathieu-Daudé     gen_load_gpr_hi(bx, a->rt);
5320bc69372SPhilippe Mathieu-Daudé     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
5330bc69372SPhilippe Mathieu-Daudé     return true;
5340bc69372SPhilippe Mathieu-Daudé }
5350bc69372SPhilippe Mathieu-Daudé 
536a2b0a27dSPhilippe Mathieu-Daudé /*
537a2b0a27dSPhilippe Mathieu-Daudé  *     Others (16 instructions)
538a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
539a2b0a27dSPhilippe Mathieu-Daudé  * PCPYH   rd, rt            Parallel Copy Halfword
540a2b0a27dSPhilippe Mathieu-Daudé  * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
541a2b0a27dSPhilippe Mathieu-Daudé  * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
542a2b0a27dSPhilippe Mathieu-Daudé  * PREVH   rd, rt            Parallel Reverse Halfword
543a2b0a27dSPhilippe Mathieu-Daudé  * PINTH   rd, rs, rt        Parallel Interleave Halfword
544a2b0a27dSPhilippe Mathieu-Daudé  * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
545a2b0a27dSPhilippe Mathieu-Daudé  * PEXEH   rd, rt            Parallel Exchange Even Halfword
546a2b0a27dSPhilippe Mathieu-Daudé  * PEXCH   rd, rt            Parallel Exchange Center Halfword
547a2b0a27dSPhilippe Mathieu-Daudé  * PEXEW   rd, rt            Parallel Exchange Even Word
548a2b0a27dSPhilippe Mathieu-Daudé  * PEXCW   rd, rt            Parallel Exchange Center Word
549a2b0a27dSPhilippe Mathieu-Daudé  * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
550a2b0a27dSPhilippe Mathieu-Daudé  * MFSA    rd                Move from Shift Amount Register
551a2b0a27dSPhilippe Mathieu-Daudé  * MTSA    rs                Move to Shift Amount Register
552a2b0a27dSPhilippe Mathieu-Daudé  * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
553a2b0a27dSPhilippe Mathieu-Daudé  * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
554a2b0a27dSPhilippe Mathieu-Daudé  * PROT3W  rd, rt            Parallel Rotate 3 Words
555a2b0a27dSPhilippe Mathieu-Daudé  */
556a2b0a27dSPhilippe Mathieu-Daudé 
557a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Halfword */
55834fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCPYH(DisasContext *s, arg_r *a)
559a2b0a27dSPhilippe Mathieu-Daudé {
560a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
561a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
562a2b0a27dSPhilippe Mathieu-Daudé         return true;
563a2b0a27dSPhilippe Mathieu-Daudé     }
564a2b0a27dSPhilippe Mathieu-Daudé 
565a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
566a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
567a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
568a2b0a27dSPhilippe Mathieu-Daudé         return true;
569a2b0a27dSPhilippe Mathieu-Daudé     }
570a2b0a27dSPhilippe Mathieu-Daudé 
571a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
572a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
573a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
574a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
575a2b0a27dSPhilippe Mathieu-Daudé 
576a2b0a27dSPhilippe Mathieu-Daudé     return true;
577a2b0a27dSPhilippe Mathieu-Daudé }
578a2b0a27dSPhilippe Mathieu-Daudé 
579a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Lower Doubleword */
58034fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCPYLD(DisasContext *s, arg_r *a)
581a2b0a27dSPhilippe Mathieu-Daudé {
582a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
583a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
584a2b0a27dSPhilippe Mathieu-Daudé         return true;
585a2b0a27dSPhilippe Mathieu-Daudé     }
586a2b0a27dSPhilippe Mathieu-Daudé 
587a2b0a27dSPhilippe Mathieu-Daudé     if (a->rs == 0) {
588a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
589a2b0a27dSPhilippe Mathieu-Daudé     } else {
590a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
591a2b0a27dSPhilippe Mathieu-Daudé     }
592a2b0a27dSPhilippe Mathieu-Daudé 
593a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
594a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
595a2b0a27dSPhilippe Mathieu-Daudé     } else if (a->rd != a->rt) {
596a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
597a2b0a27dSPhilippe Mathieu-Daudé     }
598a2b0a27dSPhilippe Mathieu-Daudé 
599a2b0a27dSPhilippe Mathieu-Daudé     return true;
600a2b0a27dSPhilippe Mathieu-Daudé }
601a2b0a27dSPhilippe Mathieu-Daudé 
602a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Upper Doubleword */
60334fe9fa3SPhilippe Mathieu-Daudé static bool trans_PCPYUD(DisasContext *s, arg_r *a)
604a2b0a27dSPhilippe Mathieu-Daudé {
605a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
606a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
607a2b0a27dSPhilippe Mathieu-Daudé         return true;
608a2b0a27dSPhilippe Mathieu-Daudé     }
609a2b0a27dSPhilippe Mathieu-Daudé 
610a2b0a27dSPhilippe Mathieu-Daudé     gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
611a2b0a27dSPhilippe Mathieu-Daudé 
612a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
613a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
614a2b0a27dSPhilippe Mathieu-Daudé     } else if (a->rd != a->rt) {
615a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
616a2b0a27dSPhilippe Mathieu-Daudé     }
617a2b0a27dSPhilippe Mathieu-Daudé 
618a2b0a27dSPhilippe Mathieu-Daudé     return true;
619a2b0a27dSPhilippe Mathieu-Daudé }
620dce4808fSPhilippe Mathieu-Daudé 
621dce4808fSPhilippe Mathieu-Daudé /* Parallel Rotate 3 Words Left */
62234fe9fa3SPhilippe Mathieu-Daudé static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
623dce4808fSPhilippe Mathieu-Daudé {
624dce4808fSPhilippe Mathieu-Daudé     TCGv_i64 ax;
625dce4808fSPhilippe Mathieu-Daudé 
626dce4808fSPhilippe Mathieu-Daudé     if (a->rd == 0) {
627dce4808fSPhilippe Mathieu-Daudé         /* nop */
628dce4808fSPhilippe Mathieu-Daudé         return true;
629dce4808fSPhilippe Mathieu-Daudé     }
630dce4808fSPhilippe Mathieu-Daudé     if (a->rt == 0) {
631dce4808fSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
632dce4808fSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
633dce4808fSPhilippe Mathieu-Daudé         return true;
634dce4808fSPhilippe Mathieu-Daudé     }
635dce4808fSPhilippe Mathieu-Daudé 
636dce4808fSPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
637dce4808fSPhilippe Mathieu-Daudé 
638dce4808fSPhilippe Mathieu-Daudé     tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
639dce4808fSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
640dce4808fSPhilippe Mathieu-Daudé 
641dce4808fSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
642dce4808fSPhilippe Mathieu-Daudé     tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
643dce4808fSPhilippe Mathieu-Daudé     return true;
644dce4808fSPhilippe Mathieu-Daudé }
645