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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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