xref: /openbmc/qemu/target/mips/tcg/tx79_translate.c (revision a9ea77f2)
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é 
67a2b0a27dSPhilippe Mathieu-Daudé static bool trans_MFHI1(DisasContext *ctx, arg_rtype *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é 
74a2b0a27dSPhilippe Mathieu-Daudé static bool trans_MFLO1(DisasContext *ctx, arg_rtype *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é 
81a2b0a27dSPhilippe Mathieu-Daudé static bool trans_MTHI1(DisasContext *ctx, arg_rtype *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é 
88a2b0a27dSPhilippe Mathieu-Daudé static bool trans_MTLO1(DisasContext *ctx, arg_rtype *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é 
1192d4ab117SPhilippe Mathieu-Daudé static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *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é 
1422d4ab117SPhilippe Mathieu-Daudé     tcg_temp_free(bx);
1432d4ab117SPhilippe Mathieu-Daudé     tcg_temp_free(ax);
1442d4ab117SPhilippe Mathieu-Daudé 
1452d4ab117SPhilippe Mathieu-Daudé     return true;
1462d4ab117SPhilippe Mathieu-Daudé }
1472d4ab117SPhilippe Mathieu-Daudé 
148709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Byte */
149709324dcSPhilippe Mathieu-Daudé static bool trans_PSUBB(DisasContext *ctx, arg_rtype *a)
150709324dcSPhilippe Mathieu-Daudé {
151709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
152709324dcSPhilippe Mathieu-Daudé }
153709324dcSPhilippe Mathieu-Daudé 
154709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Halfword */
155709324dcSPhilippe Mathieu-Daudé static bool trans_PSUBH(DisasContext *ctx, arg_rtype *a)
156709324dcSPhilippe Mathieu-Daudé {
157709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
158709324dcSPhilippe Mathieu-Daudé }
159709324dcSPhilippe Mathieu-Daudé 
160709324dcSPhilippe Mathieu-Daudé /* Parallel Subtract Word */
161709324dcSPhilippe Mathieu-Daudé static bool trans_PSUBW(DisasContext *ctx, arg_rtype *a)
162709324dcSPhilippe Mathieu-Daudé {
163709324dcSPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
164709324dcSPhilippe Mathieu-Daudé }
165709324dcSPhilippe Mathieu-Daudé 
166a2b0a27dSPhilippe Mathieu-Daudé /*
167a2b0a27dSPhilippe Mathieu-Daudé  *     Min/Max (4 instructions)
168a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
169a2b0a27dSPhilippe Mathieu-Daudé  * PMAXH   rd, rs, rt        Parallel Maximum Halfword
170a2b0a27dSPhilippe Mathieu-Daudé  * PMINH   rd, rs, rt        Parallel Minimum Halfword
171a2b0a27dSPhilippe Mathieu-Daudé  * PMAXW   rd, rs, rt        Parallel Maximum Word
172a2b0a27dSPhilippe Mathieu-Daudé  * PMINW   rd, rs, rt        Parallel Minimum Word
173a2b0a27dSPhilippe Mathieu-Daudé  */
174a2b0a27dSPhilippe Mathieu-Daudé 
175a2b0a27dSPhilippe Mathieu-Daudé /*
176a2b0a27dSPhilippe Mathieu-Daudé  *     Absolute (2 instructions)
177a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------------
178a2b0a27dSPhilippe Mathieu-Daudé  * PABSH   rd, rt            Parallel Absolute Halfword
179a2b0a27dSPhilippe Mathieu-Daudé  * PABSW   rd, rt            Parallel Absolute Word
180a2b0a27dSPhilippe Mathieu-Daudé  */
181a2b0a27dSPhilippe Mathieu-Daudé 
182a2b0a27dSPhilippe Mathieu-Daudé /*
183a2b0a27dSPhilippe Mathieu-Daudé  *     Logical (4 instructions)
184a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
185a2b0a27dSPhilippe Mathieu-Daudé  * PAND    rd, rs, rt        Parallel AND
186a2b0a27dSPhilippe Mathieu-Daudé  * POR     rd, rs, rt        Parallel OR
187a2b0a27dSPhilippe Mathieu-Daudé  * PXOR    rd, rs, rt        Parallel XOR
188a2b0a27dSPhilippe Mathieu-Daudé  * PNOR    rd, rs, rt        Parallel NOR
189a2b0a27dSPhilippe Mathieu-Daudé  */
190a2b0a27dSPhilippe Mathieu-Daudé 
1912d4ab117SPhilippe Mathieu-Daudé /* Parallel And */
1922d4ab117SPhilippe Mathieu-Daudé static bool trans_PAND(DisasContext *ctx, arg_rtype *a)
1932d4ab117SPhilippe Mathieu-Daudé {
1942d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
1952d4ab117SPhilippe Mathieu-Daudé }
1962d4ab117SPhilippe Mathieu-Daudé 
1972d4ab117SPhilippe Mathieu-Daudé /* Parallel Or */
1982d4ab117SPhilippe Mathieu-Daudé static bool trans_POR(DisasContext *ctx, arg_rtype *a)
1992d4ab117SPhilippe Mathieu-Daudé {
2002d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
2012d4ab117SPhilippe Mathieu-Daudé }
2022d4ab117SPhilippe Mathieu-Daudé 
2032d4ab117SPhilippe Mathieu-Daudé /* Parallel Exclusive Or */
2042d4ab117SPhilippe Mathieu-Daudé static bool trans_PXOR(DisasContext *ctx, arg_rtype *a)
2052d4ab117SPhilippe Mathieu-Daudé {
2062d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
2072d4ab117SPhilippe Mathieu-Daudé }
2082d4ab117SPhilippe Mathieu-Daudé 
2092d4ab117SPhilippe Mathieu-Daudé /* Parallel Not Or */
2102d4ab117SPhilippe Mathieu-Daudé static bool trans_PNOR(DisasContext *ctx, arg_rtype *a)
2112d4ab117SPhilippe Mathieu-Daudé {
2122d4ab117SPhilippe Mathieu-Daudé     return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
2132d4ab117SPhilippe Mathieu-Daudé }
2142d4ab117SPhilippe Mathieu-Daudé 
215a2b0a27dSPhilippe Mathieu-Daudé /*
216a2b0a27dSPhilippe Mathieu-Daudé  *     Shift (9 instructions)
217a2b0a27dSPhilippe Mathieu-Daudé  *     ----------------------
218a2b0a27dSPhilippe Mathieu-Daudé  * PSLLH   rd, rt, sa        Parallel Shift Left Logical Halfword
219a2b0a27dSPhilippe Mathieu-Daudé  * PSRLH   rd, rt, sa        Parallel Shift Right Logical Halfword
220a2b0a27dSPhilippe Mathieu-Daudé  * PSRAH   rd, rt, sa        Parallel Shift Right Arithmetic Halfword
221a2b0a27dSPhilippe Mathieu-Daudé  * PSLLW   rd, rt, sa        Parallel Shift Left Logical Word
222a2b0a27dSPhilippe Mathieu-Daudé  * PSRLW   rd, rt, sa        Parallel Shift Right Logical Word
223a2b0a27dSPhilippe Mathieu-Daudé  * PSRAW   rd, rt, sa        Parallel Shift Right Arithmetic Word
224a2b0a27dSPhilippe Mathieu-Daudé  * PSLLVW  rd, rt, rs        Parallel Shift Left Logical Variable Word
225a2b0a27dSPhilippe Mathieu-Daudé  * PSRLVW  rd, rt, rs        Parallel Shift Right Logical Variable Word
226a2b0a27dSPhilippe Mathieu-Daudé  * PSRAVW  rd, rt, rs        Parallel Shift Right Arithmetic Variable Word
227a2b0a27dSPhilippe Mathieu-Daudé  */
228a2b0a27dSPhilippe Mathieu-Daudé 
229a2b0a27dSPhilippe Mathieu-Daudé /*
230a2b0a27dSPhilippe Mathieu-Daudé  *     Compare (6 instructions)
231a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
232a2b0a27dSPhilippe Mathieu-Daudé  * PCGTB   rd, rs, rt        Parallel Compare for Greater Than Byte
233a2b0a27dSPhilippe Mathieu-Daudé  * PCEQB   rd, rs, rt        Parallel Compare for Equal Byte
234a2b0a27dSPhilippe Mathieu-Daudé  * PCGTH   rd, rs, rt        Parallel Compare for Greater Than Halfword
235a2b0a27dSPhilippe Mathieu-Daudé  * PCEQH   rd, rs, rt        Parallel Compare for Equal Halfword
236a2b0a27dSPhilippe Mathieu-Daudé  * PCGTW   rd, rs, rt        Parallel Compare for Greater Than Word
237a2b0a27dSPhilippe Mathieu-Daudé  * PCEQW   rd, rs, rt        Parallel Compare for Equal Word
238a2b0a27dSPhilippe Mathieu-Daudé  */
239a2b0a27dSPhilippe Mathieu-Daudé 
240a2b0a27dSPhilippe Mathieu-Daudé /*
241a2b0a27dSPhilippe Mathieu-Daudé  *     LZC (1 instruction)
242a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------
243a2b0a27dSPhilippe Mathieu-Daudé  * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
244a2b0a27dSPhilippe Mathieu-Daudé  */
245a2b0a27dSPhilippe Mathieu-Daudé 
246a2b0a27dSPhilippe Mathieu-Daudé /*
247a2b0a27dSPhilippe Mathieu-Daudé  *     Quadword Load and Store (2 instructions)
248a2b0a27dSPhilippe Mathieu-Daudé  *     ----------------------------------------
249a2b0a27dSPhilippe Mathieu-Daudé  * LQ      rt, offset(base)  Load Quadword
250a2b0a27dSPhilippe Mathieu-Daudé  * SQ      rt, offset(base)  Store Quadword
251a2b0a27dSPhilippe Mathieu-Daudé  */
252a2b0a27dSPhilippe Mathieu-Daudé 
253a2b0a27dSPhilippe Mathieu-Daudé /*
254a2b0a27dSPhilippe Mathieu-Daudé  *     Multiply and Divide (19 instructions)
255a2b0a27dSPhilippe Mathieu-Daudé  *     -------------------------------------
256a2b0a27dSPhilippe Mathieu-Daudé  * PMULTW  rd, rs, rt        Parallel Multiply Word
257a2b0a27dSPhilippe Mathieu-Daudé  * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
258a2b0a27dSPhilippe Mathieu-Daudé  * PDIVW   rs, rt            Parallel Divide Word
259a2b0a27dSPhilippe Mathieu-Daudé  * PDIVUW  rs, rt            Parallel Divide Unsigned Word
260a2b0a27dSPhilippe Mathieu-Daudé  * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
261a2b0a27dSPhilippe Mathieu-Daudé  * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
262a2b0a27dSPhilippe Mathieu-Daudé  * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
263a2b0a27dSPhilippe Mathieu-Daudé  * PMULTH  rd, rs, rt        Parallel Multiply Halfword
264a2b0a27dSPhilippe Mathieu-Daudé  * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
265a2b0a27dSPhilippe Mathieu-Daudé  * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
266a2b0a27dSPhilippe Mathieu-Daudé  * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
267a2b0a27dSPhilippe Mathieu-Daudé  * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
268a2b0a27dSPhilippe Mathieu-Daudé  * PDIVBW  rs, rt            Parallel Divide Broadcast Word
269a2b0a27dSPhilippe Mathieu-Daudé  * PMFHI   rd                Parallel Move From HI Register
270a2b0a27dSPhilippe Mathieu-Daudé  * PMFLO   rd                Parallel Move From LO Register
271a2b0a27dSPhilippe Mathieu-Daudé  * PMTHI   rs                Parallel Move To HI Register
272a2b0a27dSPhilippe Mathieu-Daudé  * PMTLO   rs                Parallel Move To LO Register
273a2b0a27dSPhilippe Mathieu-Daudé  * PMFHL   rd                Parallel Move From HI/LO Register
274a2b0a27dSPhilippe Mathieu-Daudé  * PMTHL   rs                Parallel Move To HI/LO Register
275a2b0a27dSPhilippe Mathieu-Daudé  */
276a2b0a27dSPhilippe Mathieu-Daudé 
277a2b0a27dSPhilippe Mathieu-Daudé /*
278a2b0a27dSPhilippe Mathieu-Daudé  *     Pack/Extend (11 instructions)
279a2b0a27dSPhilippe Mathieu-Daudé  *     -----------------------------
280a2b0a27dSPhilippe Mathieu-Daudé  * PPAC5   rd, rt            Parallel Pack to 5 bits
281a2b0a27dSPhilippe Mathieu-Daudé  * PPACB   rd, rs, rt        Parallel Pack to Byte
282a2b0a27dSPhilippe Mathieu-Daudé  * PPACH   rd, rs, rt        Parallel Pack to Halfword
283a2b0a27dSPhilippe Mathieu-Daudé  * PPACW   rd, rs, rt        Parallel Pack to Word
284a2b0a27dSPhilippe Mathieu-Daudé  * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
285a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
286a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
287a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
288a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
289a2b0a27dSPhilippe Mathieu-Daudé  * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
290a2b0a27dSPhilippe Mathieu-Daudé  * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
291a2b0a27dSPhilippe Mathieu-Daudé  */
292a2b0a27dSPhilippe Mathieu-Daudé 
2930bc69372SPhilippe Mathieu-Daudé static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
2940bc69372SPhilippe Mathieu-Daudé {
2950bc69372SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(dl, b, a, 32, 32);
2960bc69372SPhilippe Mathieu-Daudé     tcg_gen_shri_i64(b, b, 32);
2970bc69372SPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(dh, a, b, 0, 32);
2980bc69372SPhilippe Mathieu-Daudé }
2990bc69372SPhilippe Mathieu-Daudé 
300*a9ea77f2SPhilippe Mathieu-Daudé static bool trans_PEXTLx(DisasContext *ctx, arg_rtype *a, unsigned wlen)
301*a9ea77f2SPhilippe Mathieu-Daudé {
302*a9ea77f2SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
303*a9ea77f2SPhilippe Mathieu-Daudé 
304*a9ea77f2SPhilippe Mathieu-Daudé     if (a->rd == 0) {
305*a9ea77f2SPhilippe Mathieu-Daudé         /* nop */
306*a9ea77f2SPhilippe Mathieu-Daudé         return true;
307*a9ea77f2SPhilippe Mathieu-Daudé     }
308*a9ea77f2SPhilippe Mathieu-Daudé 
309*a9ea77f2SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
310*a9ea77f2SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
311*a9ea77f2SPhilippe Mathieu-Daudé 
312*a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
313*a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
314*a9ea77f2SPhilippe Mathieu-Daudé 
315*a9ea77f2SPhilippe Mathieu-Daudé     /* Lower half */
316*a9ea77f2SPhilippe Mathieu-Daudé     for (int i = 0; i < 64 / (2 * wlen); i++) {
317*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr[a->rd],
318*a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
319*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr[a->rd],
320*a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
321*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(bx, bx, wlen);
322*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(ax, ax, wlen);
323*a9ea77f2SPhilippe Mathieu-Daudé     }
324*a9ea77f2SPhilippe Mathieu-Daudé     /* Upper half */
325*a9ea77f2SPhilippe Mathieu-Daudé     for (int i = 0; i < 64 / (2 * wlen); i++) {
326*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
327*a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
328*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
329*a9ea77f2SPhilippe Mathieu-Daudé                             cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
330*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(bx, bx, wlen);
331*a9ea77f2SPhilippe Mathieu-Daudé         tcg_gen_shri_i64(ax, ax, wlen);
332*a9ea77f2SPhilippe Mathieu-Daudé     }
333*a9ea77f2SPhilippe Mathieu-Daudé 
334*a9ea77f2SPhilippe Mathieu-Daudé     tcg_temp_free(bx);
335*a9ea77f2SPhilippe Mathieu-Daudé     tcg_temp_free(ax);
336*a9ea77f2SPhilippe Mathieu-Daudé 
337*a9ea77f2SPhilippe Mathieu-Daudé     return true;
338*a9ea77f2SPhilippe Mathieu-Daudé }
339*a9ea77f2SPhilippe Mathieu-Daudé 
340*a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Byte */
341*a9ea77f2SPhilippe Mathieu-Daudé static bool trans_PEXTLB(DisasContext *ctx, arg_rtype *a)
342*a9ea77f2SPhilippe Mathieu-Daudé {
343*a9ea77f2SPhilippe Mathieu-Daudé     return trans_PEXTLx(ctx, a, 8);
344*a9ea77f2SPhilippe Mathieu-Daudé }
345*a9ea77f2SPhilippe Mathieu-Daudé 
346*a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Halfword */
347*a9ea77f2SPhilippe Mathieu-Daudé static bool trans_PEXTLH(DisasContext *ctx, arg_rtype *a)
348*a9ea77f2SPhilippe Mathieu-Daudé {
349*a9ea77f2SPhilippe Mathieu-Daudé     return trans_PEXTLx(ctx, a, 16);
350*a9ea77f2SPhilippe Mathieu-Daudé }
351*a9ea77f2SPhilippe Mathieu-Daudé 
352*a9ea77f2SPhilippe Mathieu-Daudé /* Parallel Extend Lower from Word */
353*a9ea77f2SPhilippe Mathieu-Daudé static bool trans_PEXTLW(DisasContext *ctx, arg_rtype *a)
354*a9ea77f2SPhilippe Mathieu-Daudé {
355*a9ea77f2SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
356*a9ea77f2SPhilippe Mathieu-Daudé 
357*a9ea77f2SPhilippe Mathieu-Daudé     if (a->rd == 0) {
358*a9ea77f2SPhilippe Mathieu-Daudé         /* nop */
359*a9ea77f2SPhilippe Mathieu-Daudé         return true;
360*a9ea77f2SPhilippe Mathieu-Daudé     }
361*a9ea77f2SPhilippe Mathieu-Daudé 
362*a9ea77f2SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
363*a9ea77f2SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
364*a9ea77f2SPhilippe Mathieu-Daudé 
365*a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(ax, a->rs);
366*a9ea77f2SPhilippe Mathieu-Daudé     gen_load_gpr(bx, a->rt);
367*a9ea77f2SPhilippe Mathieu-Daudé     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
368*a9ea77f2SPhilippe Mathieu-Daudé 
369*a9ea77f2SPhilippe Mathieu-Daudé     tcg_temp_free(bx);
370*a9ea77f2SPhilippe Mathieu-Daudé     tcg_temp_free(ax);
371*a9ea77f2SPhilippe Mathieu-Daudé 
372*a9ea77f2SPhilippe Mathieu-Daudé     return true;
373*a9ea77f2SPhilippe Mathieu-Daudé }
374*a9ea77f2SPhilippe Mathieu-Daudé 
3750bc69372SPhilippe Mathieu-Daudé /* Parallel Extend Upper from Word */
3760bc69372SPhilippe Mathieu-Daudé static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
3770bc69372SPhilippe Mathieu-Daudé {
3780bc69372SPhilippe Mathieu-Daudé     TCGv_i64 ax, bx;
3790bc69372SPhilippe Mathieu-Daudé 
3800bc69372SPhilippe Mathieu-Daudé     if (a->rd == 0) {
3810bc69372SPhilippe Mathieu-Daudé         /* nop */
3820bc69372SPhilippe Mathieu-Daudé         return true;
3830bc69372SPhilippe Mathieu-Daudé     }
3840bc69372SPhilippe Mathieu-Daudé 
3850bc69372SPhilippe Mathieu-Daudé     ax = tcg_temp_new_i64();
3860bc69372SPhilippe Mathieu-Daudé     bx = tcg_temp_new_i64();
3870bc69372SPhilippe Mathieu-Daudé 
3880bc69372SPhilippe Mathieu-Daudé     gen_load_gpr_hi(ax, a->rs);
3890bc69372SPhilippe Mathieu-Daudé     gen_load_gpr_hi(bx, a->rt);
3900bc69372SPhilippe Mathieu-Daudé     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
3910bc69372SPhilippe Mathieu-Daudé 
3920bc69372SPhilippe Mathieu-Daudé     tcg_temp_free(bx);
3930bc69372SPhilippe Mathieu-Daudé     tcg_temp_free(ax);
3940bc69372SPhilippe Mathieu-Daudé 
3950bc69372SPhilippe Mathieu-Daudé     return true;
3960bc69372SPhilippe Mathieu-Daudé }
3970bc69372SPhilippe Mathieu-Daudé 
398a2b0a27dSPhilippe Mathieu-Daudé /*
399a2b0a27dSPhilippe Mathieu-Daudé  *     Others (16 instructions)
400a2b0a27dSPhilippe Mathieu-Daudé  *     ------------------------
401a2b0a27dSPhilippe Mathieu-Daudé  * PCPYH   rd, rt            Parallel Copy Halfword
402a2b0a27dSPhilippe Mathieu-Daudé  * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
403a2b0a27dSPhilippe Mathieu-Daudé  * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
404a2b0a27dSPhilippe Mathieu-Daudé  * PREVH   rd, rt            Parallel Reverse Halfword
405a2b0a27dSPhilippe Mathieu-Daudé  * PINTH   rd, rs, rt        Parallel Interleave Halfword
406a2b0a27dSPhilippe Mathieu-Daudé  * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
407a2b0a27dSPhilippe Mathieu-Daudé  * PEXEH   rd, rt            Parallel Exchange Even Halfword
408a2b0a27dSPhilippe Mathieu-Daudé  * PEXCH   rd, rt            Parallel Exchange Center Halfword
409a2b0a27dSPhilippe Mathieu-Daudé  * PEXEW   rd, rt            Parallel Exchange Even Word
410a2b0a27dSPhilippe Mathieu-Daudé  * PEXCW   rd, rt            Parallel Exchange Center Word
411a2b0a27dSPhilippe Mathieu-Daudé  * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
412a2b0a27dSPhilippe Mathieu-Daudé  * MFSA    rd                Move from Shift Amount Register
413a2b0a27dSPhilippe Mathieu-Daudé  * MTSA    rs                Move to Shift Amount Register
414a2b0a27dSPhilippe Mathieu-Daudé  * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
415a2b0a27dSPhilippe Mathieu-Daudé  * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
416a2b0a27dSPhilippe Mathieu-Daudé  * PROT3W  rd, rt            Parallel Rotate 3 Words
417a2b0a27dSPhilippe Mathieu-Daudé  */
418a2b0a27dSPhilippe Mathieu-Daudé 
419a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Halfword */
420a2b0a27dSPhilippe Mathieu-Daudé static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
421a2b0a27dSPhilippe Mathieu-Daudé {
422a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
423a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
424a2b0a27dSPhilippe Mathieu-Daudé         return true;
425a2b0a27dSPhilippe Mathieu-Daudé     }
426a2b0a27dSPhilippe Mathieu-Daudé 
427a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
428a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
429a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
430a2b0a27dSPhilippe Mathieu-Daudé         return true;
431a2b0a27dSPhilippe Mathieu-Daudé     }
432a2b0a27dSPhilippe Mathieu-Daudé 
433a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
434a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
435a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
436a2b0a27dSPhilippe Mathieu-Daudé     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
437a2b0a27dSPhilippe Mathieu-Daudé 
438a2b0a27dSPhilippe Mathieu-Daudé     return true;
439a2b0a27dSPhilippe Mathieu-Daudé }
440a2b0a27dSPhilippe Mathieu-Daudé 
441a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Lower Doubleword */
442a2b0a27dSPhilippe Mathieu-Daudé static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
443a2b0a27dSPhilippe Mathieu-Daudé {
444a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
445a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
446a2b0a27dSPhilippe Mathieu-Daudé         return true;
447a2b0a27dSPhilippe Mathieu-Daudé     }
448a2b0a27dSPhilippe Mathieu-Daudé 
449a2b0a27dSPhilippe Mathieu-Daudé     if (a->rs == 0) {
450a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
451a2b0a27dSPhilippe Mathieu-Daudé     } else {
452a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
453a2b0a27dSPhilippe Mathieu-Daudé     }
454a2b0a27dSPhilippe Mathieu-Daudé 
455a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
456a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
457a2b0a27dSPhilippe Mathieu-Daudé     } else if (a->rd != a->rt) {
458a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
459a2b0a27dSPhilippe Mathieu-Daudé     }
460a2b0a27dSPhilippe Mathieu-Daudé 
461a2b0a27dSPhilippe Mathieu-Daudé     return true;
462a2b0a27dSPhilippe Mathieu-Daudé }
463a2b0a27dSPhilippe Mathieu-Daudé 
464a2b0a27dSPhilippe Mathieu-Daudé /* Parallel Copy Upper Doubleword */
465a2b0a27dSPhilippe Mathieu-Daudé static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
466a2b0a27dSPhilippe Mathieu-Daudé {
467a2b0a27dSPhilippe Mathieu-Daudé     if (a->rd == 0) {
468a2b0a27dSPhilippe Mathieu-Daudé         /* nop */
469a2b0a27dSPhilippe Mathieu-Daudé         return true;
470a2b0a27dSPhilippe Mathieu-Daudé     }
471a2b0a27dSPhilippe Mathieu-Daudé 
472a2b0a27dSPhilippe Mathieu-Daudé     gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
473a2b0a27dSPhilippe Mathieu-Daudé 
474a2b0a27dSPhilippe Mathieu-Daudé     if (a->rt == 0) {
475a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
476a2b0a27dSPhilippe Mathieu-Daudé     } else if (a->rd != a->rt) {
477a2b0a27dSPhilippe Mathieu-Daudé         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
478a2b0a27dSPhilippe Mathieu-Daudé     }
479a2b0a27dSPhilippe Mathieu-Daudé 
480a2b0a27dSPhilippe Mathieu-Daudé     return true;
481a2b0a27dSPhilippe Mathieu-Daudé }
482