xref: /openbmc/qemu/target/mips/tcg/tx79_translate.c (revision 0bc69372)
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 /*
241  *     LZC (1 instruction)
242  *     -------------------
243  * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
244  */
245 
246 /*
247  *     Quadword Load and Store (2 instructions)
248  *     ----------------------------------------
249  * LQ      rt, offset(base)  Load Quadword
250  * SQ      rt, offset(base)  Store Quadword
251  */
252 
253 /*
254  *     Multiply and Divide (19 instructions)
255  *     -------------------------------------
256  * PMULTW  rd, rs, rt        Parallel Multiply Word
257  * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
258  * PDIVW   rs, rt            Parallel Divide Word
259  * PDIVUW  rs, rt            Parallel Divide Unsigned Word
260  * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
261  * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
262  * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
263  * PMULTH  rd, rs, rt        Parallel Multiply Halfword
264  * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
265  * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
266  * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
267  * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
268  * PDIVBW  rs, rt            Parallel Divide Broadcast Word
269  * PMFHI   rd                Parallel Move From HI Register
270  * PMFLO   rd                Parallel Move From LO Register
271  * PMTHI   rs                Parallel Move To HI Register
272  * PMTLO   rs                Parallel Move To LO Register
273  * PMFHL   rd                Parallel Move From HI/LO Register
274  * PMTHL   rs                Parallel Move To HI/LO Register
275  */
276 
277 /*
278  *     Pack/Extend (11 instructions)
279  *     -----------------------------
280  * PPAC5   rd, rt            Parallel Pack to 5 bits
281  * PPACB   rd, rs, rt        Parallel Pack to Byte
282  * PPACH   rd, rs, rt        Parallel Pack to Halfword
283  * PPACW   rd, rs, rt        Parallel Pack to Word
284  * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
285  * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
286  * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
287  * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
288  * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
289  * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
290  * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
291  */
292 
293 static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
294 {
295     tcg_gen_deposit_i64(dl, b, a, 32, 32);
296     tcg_gen_shri_i64(b, b, 32);
297     tcg_gen_deposit_i64(dh, a, b, 0, 32);
298 }
299 
300 /* Parallel Extend Upper from Word */
301 static bool trans_PEXTUW(DisasContext *ctx, arg_rtype *a)
302 {
303     TCGv_i64 ax, bx;
304 
305     if (a->rd == 0) {
306         /* nop */
307         return true;
308     }
309 
310     ax = tcg_temp_new_i64();
311     bx = tcg_temp_new_i64();
312 
313     gen_load_gpr_hi(ax, a->rs);
314     gen_load_gpr_hi(bx, a->rt);
315     gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
316 
317     tcg_temp_free(bx);
318     tcg_temp_free(ax);
319 
320     return true;
321 }
322 
323 /*
324  *     Others (16 instructions)
325  *     ------------------------
326  * PCPYH   rd, rt            Parallel Copy Halfword
327  * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
328  * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
329  * PREVH   rd, rt            Parallel Reverse Halfword
330  * PINTH   rd, rs, rt        Parallel Interleave Halfword
331  * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
332  * PEXEH   rd, rt            Parallel Exchange Even Halfword
333  * PEXCH   rd, rt            Parallel Exchange Center Halfword
334  * PEXEW   rd, rt            Parallel Exchange Even Word
335  * PEXCW   rd, rt            Parallel Exchange Center Word
336  * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
337  * MFSA    rd                Move from Shift Amount Register
338  * MTSA    rs                Move to Shift Amount Register
339  * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
340  * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
341  * PROT3W  rd, rt            Parallel Rotate 3 Words
342  */
343 
344 /* Parallel Copy Halfword */
345 static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
346 {
347     if (a->rd == 0) {
348         /* nop */
349         return true;
350     }
351 
352     if (a->rt == 0) {
353         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
354         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
355         return true;
356     }
357 
358     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
359     tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
360     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
361     tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
362 
363     return true;
364 }
365 
366 /* Parallel Copy Lower Doubleword */
367 static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
368 {
369     if (a->rd == 0) {
370         /* nop */
371         return true;
372     }
373 
374     if (a->rs == 0) {
375         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
376     } else {
377         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
378     }
379 
380     if (a->rt == 0) {
381         tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
382     } else if (a->rd != a->rt) {
383         tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
384     }
385 
386     return true;
387 }
388 
389 /* Parallel Copy Upper Doubleword */
390 static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
391 {
392     if (a->rd == 0) {
393         /* nop */
394         return true;
395     }
396 
397     gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
398 
399     if (a->rt == 0) {
400         tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
401     } else if (a->rd != a->rt) {
402         tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
403     }
404 
405     return true;
406 }
407