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 "translate.h"
12 #include "tcg/tcg-op-gvec.h"
13
14 /* Include the auto-generated decoder. */
15 #include "decode-tx79.c.inc"
16
17 /*
18 * Overview of the TX79-specific instruction set
19 * =============================================
20 *
21 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
22 * are only used by the specific quadword (128-bit) LQ/SQ load/store
23 * instructions and certain multimedia instructions (MMIs). These MMIs
24 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
25 * or sixteen 8-bit paths.
26 *
27 * Reference:
28 *
29 * The Toshiba TX System RISC TX79 Core Architecture manual,
30 * https://wiki.qemu.org/File:C790.pdf
31 */
32
decode_ext_tx79(DisasContext * ctx,uint32_t insn)33 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
34 {
35 if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
36 return true;
37 }
38 return false;
39 }
40
41 /*
42 * Three-Operand Multiply and Multiply-Add (4 instructions)
43 * --------------------------------------------------------
44 * MADD [rd,] rs, rt Multiply/Add
45 * MADDU [rd,] rs, rt Multiply/Add Unsigned
46 * MULT [rd,] rs, rt Multiply (3-operand)
47 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
48 */
49
50 /*
51 * Multiply Instructions for Pipeline 1 (10 instructions)
52 * ------------------------------------------------------
53 * MULT1 [rd,] rs, rt Multiply Pipeline 1
54 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
55 * DIV1 rs, rt Divide Pipeline 1
56 * DIVU1 rs, rt Divide Unsigned Pipeline 1
57 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
58 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
59 * MFHI1 rd Move From HI1 Register
60 * MFLO1 rd Move From LO1 Register
61 * MTHI1 rs Move To HI1 Register
62 * MTLO1 rs Move To LO1 Register
63 */
64
trans_MFHI1(DisasContext * ctx,arg_r * a)65 static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
66 {
67 gen_store_gpr(cpu_HI[1], a->rd);
68
69 return true;
70 }
71
trans_MFLO1(DisasContext * ctx,arg_r * a)72 static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
73 {
74 gen_store_gpr(cpu_LO[1], a->rd);
75
76 return true;
77 }
78
trans_MTHI1(DisasContext * ctx,arg_r * a)79 static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
80 {
81 gen_load_gpr(cpu_HI[1], a->rs);
82
83 return true;
84 }
85
trans_MTLO1(DisasContext * ctx,arg_r * a)86 static bool trans_MTLO1(DisasContext *ctx, arg_r *a)
87 {
88 gen_load_gpr(cpu_LO[1], a->rs);
89
90 return true;
91 }
92
93 /*
94 * Arithmetic (19 instructions)
95 * ----------------------------
96 * PADDB rd, rs, rt Parallel Add Byte
97 * PSUBB rd, rs, rt Parallel Subtract Byte
98 * PADDH rd, rs, rt Parallel Add Halfword
99 * PSUBH rd, rs, rt Parallel Subtract Halfword
100 * PADDW rd, rs, rt Parallel Add Word
101 * PSUBW rd, rs, rt Parallel Subtract Word
102 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
103 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
104 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
105 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
106 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
107 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
108 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
109 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
110 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
111 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
112 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
113 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
114 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
115 */
116
trans_parallel_arith(DisasContext * ctx,arg_r * a,void (* gen_logic_i64)(TCGv_i64,TCGv_i64,TCGv_i64))117 static bool trans_parallel_arith(DisasContext *ctx, arg_r *a,
118 void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
119 {
120 TCGv_i64 ax, bx;
121
122 if (a->rd == 0) {
123 /* nop */
124 return true;
125 }
126
127 ax = tcg_temp_new_i64();
128 bx = tcg_temp_new_i64();
129
130 /* Lower half */
131 gen_load_gpr(ax, a->rs);
132 gen_load_gpr(bx, a->rt);
133 gen_logic_i64(cpu_gpr[a->rd], ax, bx);
134
135 /* Upper half */
136 gen_load_gpr_hi(ax, a->rs);
137 gen_load_gpr_hi(bx, a->rt);
138 gen_logic_i64(cpu_gpr_hi[a->rd], ax, bx);
139 return true;
140 }
141
142 /* Parallel Subtract Byte */
trans_PSUBB(DisasContext * ctx,arg_r * a)143 static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
144 {
145 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
146 }
147
148 /* Parallel Subtract Halfword */
trans_PSUBH(DisasContext * ctx,arg_r * a)149 static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
150 {
151 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
152 }
153
154 /* Parallel Subtract Word */
trans_PSUBW(DisasContext * ctx,arg_r * a)155 static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
156 {
157 return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
158 }
159
160 /*
161 * Min/Max (4 instructions)
162 * ------------------------
163 * PMAXH rd, rs, rt Parallel Maximum Halfword
164 * PMINH rd, rs, rt Parallel Minimum Halfword
165 * PMAXW rd, rs, rt Parallel Maximum Word
166 * PMINW rd, rs, rt Parallel Minimum Word
167 */
168
169 /*
170 * Absolute (2 instructions)
171 * -------------------------
172 * PABSH rd, rt Parallel Absolute Halfword
173 * PABSW rd, rt Parallel Absolute Word
174 */
175
176 /*
177 * Logical (4 instructions)
178 * ------------------------
179 * PAND rd, rs, rt Parallel AND
180 * POR rd, rs, rt Parallel OR
181 * PXOR rd, rs, rt Parallel XOR
182 * PNOR rd, rs, rt Parallel NOR
183 */
184
185 /* Parallel And */
trans_PAND(DisasContext * ctx,arg_r * a)186 static bool trans_PAND(DisasContext *ctx, arg_r *a)
187 {
188 return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
189 }
190
191 /* Parallel Or */
trans_POR(DisasContext * ctx,arg_r * a)192 static bool trans_POR(DisasContext *ctx, arg_r *a)
193 {
194 return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
195 }
196
197 /* Parallel Exclusive Or */
trans_PXOR(DisasContext * ctx,arg_r * a)198 static bool trans_PXOR(DisasContext *ctx, arg_r *a)
199 {
200 return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
201 }
202
203 /* Parallel Not Or */
trans_PNOR(DisasContext * ctx,arg_r * a)204 static bool trans_PNOR(DisasContext *ctx, arg_r *a)
205 {
206 return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
207 }
208
209 /*
210 * Shift (9 instructions)
211 * ----------------------
212 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
213 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
214 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
215 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
216 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
217 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
218 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
219 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
220 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
221 */
222
223 /*
224 * Compare (6 instructions)
225 * ------------------------
226 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
227 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
228 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
229 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
230 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
231 * PCEQW rd, rs, rt Parallel Compare for Equal Word
232 */
233
trans_parallel_compare(DisasContext * ctx,arg_r * a,TCGCond cond,unsigned wlen)234 static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
235 TCGCond cond, unsigned wlen)
236 {
237 TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
238
239 if (a->rd == 0) {
240 /* nop */
241 return true;
242 }
243
244 c0 = tcg_constant_tl(0);
245 c1 = tcg_constant_tl(0xffffffff);
246 ax = tcg_temp_new_i64();
247 bx = tcg_temp_new_i64();
248 t0 = tcg_temp_new_i64();
249 t1 = tcg_temp_new_i64();
250 t2 = tcg_temp_new_i64();
251
252 /* Lower half */
253 gen_load_gpr(ax, a->rs);
254 gen_load_gpr(bx, a->rt);
255 for (int i = 0; i < (64 / wlen); i++) {
256 tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
257 tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
258 tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
259 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
260 }
261 /* Upper half */
262 gen_load_gpr_hi(ax, a->rs);
263 gen_load_gpr_hi(bx, a->rt);
264 for (int i = 0; i < (64 / wlen); i++) {
265 tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
266 tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
267 tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
268 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
269 }
270 return true;
271 }
272
273 /* Parallel Compare for Greater Than Byte */
trans_PCGTB(DisasContext * ctx,arg_r * a)274 static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
275 {
276 return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
277 }
278
279 /* Parallel Compare for Equal Byte */
trans_PCEQB(DisasContext * ctx,arg_r * a)280 static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
281 {
282 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
283 }
284
285 /* Parallel Compare for Greater Than Halfword */
trans_PCGTH(DisasContext * ctx,arg_r * a)286 static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
287 {
288 return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
289 }
290
291 /* Parallel Compare for Equal Halfword */
trans_PCEQH(DisasContext * ctx,arg_r * a)292 static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
293 {
294 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
295 }
296
297 /* Parallel Compare for Greater Than Word */
trans_PCGTW(DisasContext * ctx,arg_r * a)298 static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
299 {
300 return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
301 }
302
303 /* Parallel Compare for Equal Word */
trans_PCEQW(DisasContext * ctx,arg_r * a)304 static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
305 {
306 return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
307 }
308
309 /*
310 * LZC (1 instruction)
311 * -------------------
312 * PLZCW rd, rs Parallel Leading Zero or One Count Word
313 */
314
315 /*
316 * Quadword Load and Store (2 instructions)
317 * ----------------------------------------
318 * LQ rt, offset(base) Load Quadword
319 * SQ rt, offset(base) Store Quadword
320 */
321
trans_LQ(DisasContext * ctx,arg_i * a)322 static bool trans_LQ(DisasContext *ctx, arg_i *a)
323 {
324 TCGv_i64 t0;
325 TCGv addr;
326
327 if (a->rt == 0) {
328 /* nop */
329 return true;
330 }
331
332 t0 = tcg_temp_new_i64();
333 addr = tcg_temp_new();
334
335 gen_base_offset_addr(ctx, addr, a->base, a->offset);
336 /*
337 * Clear least-significant four bits of the effective
338 * address, effectively creating an aligned address.
339 */
340 tcg_gen_andi_tl(addr, addr, ~0xf);
341
342 /* Lower half */
343 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
344 gen_store_gpr(t0, a->rt);
345
346 /* Upper half */
347 tcg_gen_addi_i64(addr, addr, 8);
348 tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
349 gen_store_gpr_hi(t0, a->rt);
350 return true;
351 }
352
trans_SQ(DisasContext * ctx,arg_i * a)353 static bool trans_SQ(DisasContext *ctx, arg_i *a)
354 {
355 TCGv_i64 t0 = tcg_temp_new_i64();
356 TCGv addr = tcg_temp_new();
357
358 gen_base_offset_addr(ctx, addr, a->base, a->offset);
359 /*
360 * Clear least-significant four bits of the effective
361 * address, effectively creating an aligned address.
362 */
363 tcg_gen_andi_tl(addr, addr, ~0xf);
364
365 /* Lower half */
366 gen_load_gpr(t0, a->rt);
367 tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
368
369 /* Upper half */
370 tcg_gen_addi_i64(addr, addr, 8);
371 gen_load_gpr_hi(t0, a->rt);
372 tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
373 return true;
374 }
375
376 /*
377 * Multiply and Divide (19 instructions)
378 * -------------------------------------
379 * PMULTW rd, rs, rt Parallel Multiply Word
380 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
381 * PDIVW rs, rt Parallel Divide Word
382 * PDIVUW rs, rt Parallel Divide Unsigned Word
383 * PMADDW rd, rs, rt Parallel Multiply-Add Word
384 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
385 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
386 * PMULTH rd, rs, rt Parallel Multiply Halfword
387 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
388 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
389 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
390 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
391 * PDIVBW rs, rt Parallel Divide Broadcast Word
392 * PMFHI rd Parallel Move From HI Register
393 * PMFLO rd Parallel Move From LO Register
394 * PMTHI rs Parallel Move To HI Register
395 * PMTLO rs Parallel Move To LO Register
396 * PMFHL rd Parallel Move From HI/LO Register
397 * PMTHL rs Parallel Move To HI/LO Register
398 */
399
400 /*
401 * Pack/Extend (11 instructions)
402 * -----------------------------
403 * PPAC5 rd, rt Parallel Pack to 5 bits
404 * PPACB rd, rs, rt Parallel Pack to Byte
405 * PPACH rd, rs, rt Parallel Pack to Halfword
406 * PPACW rd, rs, rt Parallel Pack to Word
407 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
408 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
409 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
410 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
411 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
412 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
413 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
414 */
415
416 /* Parallel Pack to Word */
trans_PPACW(DisasContext * ctx,arg_r * a)417 static bool trans_PPACW(DisasContext *ctx, arg_r *a)
418 {
419 TCGv_i64 a0, b0, t0;
420
421 if (a->rd == 0) {
422 /* nop */
423 return true;
424 }
425
426 a0 = tcg_temp_new_i64();
427 b0 = tcg_temp_new_i64();
428 t0 = tcg_temp_new_i64();
429
430 gen_load_gpr(a0, a->rs);
431 gen_load_gpr(b0, a->rt);
432
433 gen_load_gpr_hi(t0, a->rt); /* b1 */
434 tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
435
436 gen_load_gpr_hi(t0, a->rs); /* a1 */
437 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
438 return true;
439 }
440
gen_pextw(TCGv_i64 dl,TCGv_i64 dh,TCGv_i64 a,TCGv_i64 b)441 static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
442 {
443 tcg_gen_deposit_i64(dl, b, a, 32, 32);
444 tcg_gen_shri_i64(b, b, 32);
445 tcg_gen_deposit_i64(dh, a, b, 0, 32);
446 }
447
trans_PEXTLx(DisasContext * ctx,arg_r * a,unsigned wlen)448 static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
449 {
450 TCGv_i64 ax, bx;
451
452 if (a->rd == 0) {
453 /* nop */
454 return true;
455 }
456
457 ax = tcg_temp_new_i64();
458 bx = tcg_temp_new_i64();
459
460 gen_load_gpr(ax, a->rs);
461 gen_load_gpr(bx, a->rt);
462
463 /* Lower half */
464 for (int i = 0; i < 64 / (2 * wlen); i++) {
465 tcg_gen_deposit_i64(cpu_gpr[a->rd],
466 cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
467 tcg_gen_deposit_i64(cpu_gpr[a->rd],
468 cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
469 tcg_gen_shri_i64(bx, bx, wlen);
470 tcg_gen_shri_i64(ax, ax, wlen);
471 }
472 /* Upper half */
473 for (int i = 0; i < 64 / (2 * wlen); i++) {
474 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
475 cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
476 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
477 cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
478 tcg_gen_shri_i64(bx, bx, wlen);
479 tcg_gen_shri_i64(ax, ax, wlen);
480 }
481 return true;
482 }
483
484 /* Parallel Extend Lower from Byte */
trans_PEXTLB(DisasContext * ctx,arg_r * a)485 static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
486 {
487 return trans_PEXTLx(ctx, a, 8);
488 }
489
490 /* Parallel Extend Lower from Halfword */
trans_PEXTLH(DisasContext * ctx,arg_r * a)491 static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
492 {
493 return trans_PEXTLx(ctx, a, 16);
494 }
495
496 /* Parallel Extend Lower from Word */
trans_PEXTLW(DisasContext * ctx,arg_r * a)497 static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
498 {
499 TCGv_i64 ax, bx;
500
501 if (a->rd == 0) {
502 /* nop */
503 return true;
504 }
505
506 ax = tcg_temp_new_i64();
507 bx = tcg_temp_new_i64();
508
509 gen_load_gpr(ax, a->rs);
510 gen_load_gpr(bx, a->rt);
511 gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
512 return true;
513 }
514
515 /* Parallel Extend Upper from Word */
trans_PEXTUW(DisasContext * ctx,arg_r * a)516 static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
517 {
518 TCGv_i64 ax, bx;
519
520 if (a->rd == 0) {
521 /* nop */
522 return true;
523 }
524
525 ax = tcg_temp_new_i64();
526 bx = tcg_temp_new_i64();
527
528 gen_load_gpr_hi(ax, a->rs);
529 gen_load_gpr_hi(bx, a->rt);
530 gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
531 return true;
532 }
533
534 /*
535 * Others (16 instructions)
536 * ------------------------
537 * PCPYH rd, rt Parallel Copy Halfword
538 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
539 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
540 * PREVH rd, rt Parallel Reverse Halfword
541 * PINTH rd, rs, rt Parallel Interleave Halfword
542 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
543 * PEXEH rd, rt Parallel Exchange Even Halfword
544 * PEXCH rd, rt Parallel Exchange Center Halfword
545 * PEXEW rd, rt Parallel Exchange Even Word
546 * PEXCW rd, rt Parallel Exchange Center Word
547 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
548 * MFSA rd Move from Shift Amount Register
549 * MTSA rs Move to Shift Amount Register
550 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
551 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
552 * PROT3W rd, rt Parallel Rotate 3 Words
553 */
554
555 /* Parallel Copy Halfword */
trans_PCPYH(DisasContext * s,arg_r * a)556 static bool trans_PCPYH(DisasContext *s, arg_r *a)
557 {
558 if (a->rd == 0) {
559 /* nop */
560 return true;
561 }
562
563 if (a->rt == 0) {
564 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
565 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
566 return true;
567 }
568
569 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
570 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
571 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
572 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
573
574 return true;
575 }
576
577 /* Parallel Copy Lower Doubleword */
trans_PCPYLD(DisasContext * s,arg_r * a)578 static bool trans_PCPYLD(DisasContext *s, arg_r *a)
579 {
580 if (a->rd == 0) {
581 /* nop */
582 return true;
583 }
584
585 if (a->rs == 0) {
586 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
587 } else {
588 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
589 }
590
591 if (a->rt == 0) {
592 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
593 } else if (a->rd != a->rt) {
594 tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
595 }
596
597 return true;
598 }
599
600 /* Parallel Copy Upper Doubleword */
trans_PCPYUD(DisasContext * s,arg_r * a)601 static bool trans_PCPYUD(DisasContext *s, arg_r *a)
602 {
603 if (a->rd == 0) {
604 /* nop */
605 return true;
606 }
607
608 gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
609
610 if (a->rt == 0) {
611 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
612 } else if (a->rd != a->rt) {
613 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
614 }
615
616 return true;
617 }
618
619 /* Parallel Rotate 3 Words Left */
trans_PROT3W(DisasContext * ctx,arg_r * a)620 static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
621 {
622 TCGv_i64 ax;
623
624 if (a->rd == 0) {
625 /* nop */
626 return true;
627 }
628 if (a->rt == 0) {
629 tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
630 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
631 return true;
632 }
633
634 ax = tcg_temp_new_i64();
635
636 tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
637 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
638
639 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
640 tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
641 return true;
642 }
643