qemu/target/mips/tcg/tx79_translate.c
<<
>>
Prefs
   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
  35bool 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
  67static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
  68{
  69    gen_store_gpr(cpu_HI[1], a->rd);
  70
  71    return true;
  72}
  73
  74static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
  75{
  76    gen_store_gpr(cpu_LO[1], a->rd);
  77
  78    return true;
  79}
  80
  81static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
  82{
  83    gen_load_gpr(cpu_HI[1], a->rs);
  84
  85    return true;
  86}
  87
  88static bool trans_MTLO1(DisasContext *ctx, arg_r *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
 119static bool trans_parallel_arith(DisasContext *ctx, arg_r *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    return true;
 142}
 143
 144/* Parallel Subtract Byte */
 145static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
 146{
 147    return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
 148}
 149
 150/* Parallel Subtract Halfword */
 151static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
 152{
 153    return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
 154}
 155
 156/* Parallel Subtract Word */
 157static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
 158{
 159    return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
 160}
 161
 162/*
 163 *     Min/Max (4 instructions)
 164 *     ------------------------
 165 * PMAXH   rd, rs, rt        Parallel Maximum Halfword
 166 * PMINH   rd, rs, rt        Parallel Minimum Halfword
 167 * PMAXW   rd, rs, rt        Parallel Maximum Word
 168 * PMINW   rd, rs, rt        Parallel Minimum Word
 169 */
 170
 171/*
 172 *     Absolute (2 instructions)
 173 *     -------------------------
 174 * PABSH   rd, rt            Parallel Absolute Halfword
 175 * PABSW   rd, rt            Parallel Absolute Word
 176 */
 177
 178/*
 179 *     Logical (4 instructions)
 180 *     ------------------------
 181 * PAND    rd, rs, rt        Parallel AND
 182 * POR     rd, rs, rt        Parallel OR
 183 * PXOR    rd, rs, rt        Parallel XOR
 184 * PNOR    rd, rs, rt        Parallel NOR
 185 */
 186
 187/* Parallel And */
 188static bool trans_PAND(DisasContext *ctx, arg_r *a)
 189{
 190    return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
 191}
 192
 193/* Parallel Or */
 194static bool trans_POR(DisasContext *ctx, arg_r *a)
 195{
 196    return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
 197}
 198
 199/* Parallel Exclusive Or */
 200static bool trans_PXOR(DisasContext *ctx, arg_r *a)
 201{
 202    return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
 203}
 204
 205/* Parallel Not Or */
 206static bool trans_PNOR(DisasContext *ctx, arg_r *a)
 207{
 208    return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
 209}
 210
 211/*
 212 *     Shift (9 instructions)
 213 *     ----------------------
 214 * PSLLH   rd, rt, sa        Parallel Shift Left Logical Halfword
 215 * PSRLH   rd, rt, sa        Parallel Shift Right Logical Halfword
 216 * PSRAH   rd, rt, sa        Parallel Shift Right Arithmetic Halfword
 217 * PSLLW   rd, rt, sa        Parallel Shift Left Logical Word
 218 * PSRLW   rd, rt, sa        Parallel Shift Right Logical Word
 219 * PSRAW   rd, rt, sa        Parallel Shift Right Arithmetic Word
 220 * PSLLVW  rd, rt, rs        Parallel Shift Left Logical Variable Word
 221 * PSRLVW  rd, rt, rs        Parallel Shift Right Logical Variable Word
 222 * PSRAVW  rd, rt, rs        Parallel Shift Right Arithmetic Variable Word
 223 */
 224
 225/*
 226 *     Compare (6 instructions)
 227 *     ------------------------
 228 * PCGTB   rd, rs, rt        Parallel Compare for Greater Than Byte
 229 * PCEQB   rd, rs, rt        Parallel Compare for Equal Byte
 230 * PCGTH   rd, rs, rt        Parallel Compare for Greater Than Halfword
 231 * PCEQH   rd, rs, rt        Parallel Compare for Equal Halfword
 232 * PCGTW   rd, rs, rt        Parallel Compare for Greater Than Word
 233 * PCEQW   rd, rs, rt        Parallel Compare for Equal Word
 234 */
 235
 236static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
 237                                   TCGCond cond, unsigned wlen)
 238{
 239    TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
 240
 241    if (a->rd == 0) {
 242        /* nop */
 243        return true;
 244    }
 245
 246    c0 = tcg_constant_tl(0);
 247    c1 = tcg_constant_tl(0xffffffff);
 248    ax = tcg_temp_new_i64();
 249    bx = tcg_temp_new_i64();
 250    t0 = tcg_temp_new_i64();
 251    t1 = tcg_temp_new_i64();
 252    t2 = tcg_temp_new_i64();
 253
 254    /* Lower half */
 255    gen_load_gpr(ax, a->rs);
 256    gen_load_gpr(bx, a->rt);
 257    for (int i = 0; i < (64 / wlen); i++) {
 258        tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
 259        tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
 260        tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
 261        tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
 262    }
 263    /* Upper half */
 264    gen_load_gpr_hi(ax, a->rs);
 265    gen_load_gpr_hi(bx, a->rt);
 266    for (int i = 0; i < (64 / wlen); i++) {
 267        tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
 268        tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
 269        tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
 270        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
 271    }
 272    return true;
 273}
 274
 275/* Parallel Compare for Greater Than Byte */
 276static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
 277{
 278    return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
 279}
 280
 281/* Parallel Compare for Equal Byte */
 282static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
 283{
 284    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
 285}
 286
 287/* Parallel Compare for Greater Than Halfword */
 288static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
 289{
 290    return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
 291}
 292
 293/* Parallel Compare for Equal Halfword */
 294static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
 295{
 296    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
 297}
 298
 299/* Parallel Compare for Greater Than Word */
 300static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
 301{
 302    return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
 303}
 304
 305/* Parallel Compare for Equal Word */
 306static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
 307{
 308    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
 309}
 310
 311/*
 312 *     LZC (1 instruction)
 313 *     -------------------
 314 * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
 315 */
 316
 317/*
 318 *     Quadword Load and Store (2 instructions)
 319 *     ----------------------------------------
 320 * LQ      rt, offset(base)  Load Quadword
 321 * SQ      rt, offset(base)  Store Quadword
 322 */
 323
 324static bool trans_LQ(DisasContext *ctx, arg_i *a)
 325{
 326    TCGv_i64 t0;
 327    TCGv addr;
 328
 329    if (a->rt == 0) {
 330        /* nop */
 331        return true;
 332    }
 333
 334    t0 = tcg_temp_new_i64();
 335    addr = tcg_temp_new();
 336
 337    gen_base_offset_addr(ctx, addr, a->base, a->offset);
 338    /*
 339     * Clear least-significant four bits of the effective
 340     * address, effectively creating an aligned address.
 341     */
 342    tcg_gen_andi_tl(addr, addr, ~0xf);
 343
 344    /* Lower half */
 345    tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
 346    gen_store_gpr(t0, a->rt);
 347
 348    /* Upper half */
 349    tcg_gen_addi_i64(addr, addr, 8);
 350    tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
 351    gen_store_gpr_hi(t0, a->rt);
 352    return true;
 353}
 354
 355static bool trans_SQ(DisasContext *ctx, arg_i *a)
 356{
 357    TCGv_i64 t0 = tcg_temp_new_i64();
 358    TCGv addr = tcg_temp_new();
 359
 360    gen_base_offset_addr(ctx, addr, a->base, a->offset);
 361    /*
 362     * Clear least-significant four bits of the effective
 363     * address, effectively creating an aligned address.
 364     */
 365    tcg_gen_andi_tl(addr, addr, ~0xf);
 366
 367    /* Lower half */
 368    gen_load_gpr(t0, a->rt);
 369    tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
 370
 371    /* Upper half */
 372    tcg_gen_addi_i64(addr, addr, 8);
 373    gen_load_gpr_hi(t0, a->rt);
 374    tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ);
 375    return true;
 376}
 377
 378/*
 379 *     Multiply and Divide (19 instructions)
 380 *     -------------------------------------
 381 * PMULTW  rd, rs, rt        Parallel Multiply Word
 382 * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
 383 * PDIVW   rs, rt            Parallel Divide Word
 384 * PDIVUW  rs, rt            Parallel Divide Unsigned Word
 385 * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
 386 * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
 387 * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
 388 * PMULTH  rd, rs, rt        Parallel Multiply Halfword
 389 * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
 390 * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
 391 * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
 392 * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
 393 * PDIVBW  rs, rt            Parallel Divide Broadcast Word
 394 * PMFHI   rd                Parallel Move From HI Register
 395 * PMFLO   rd                Parallel Move From LO Register
 396 * PMTHI   rs                Parallel Move To HI Register
 397 * PMTLO   rs                Parallel Move To LO Register
 398 * PMFHL   rd                Parallel Move From HI/LO Register
 399 * PMTHL   rs                Parallel Move To HI/LO Register
 400 */
 401
 402/*
 403 *     Pack/Extend (11 instructions)
 404 *     -----------------------------
 405 * PPAC5   rd, rt            Parallel Pack to 5 bits
 406 * PPACB   rd, rs, rt        Parallel Pack to Byte
 407 * PPACH   rd, rs, rt        Parallel Pack to Halfword
 408 * PPACW   rd, rs, rt        Parallel Pack to Word
 409 * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
 410 * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
 411 * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
 412 * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
 413 * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
 414 * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
 415 * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
 416 */
 417
 418/* Parallel Pack to Word */
 419static bool trans_PPACW(DisasContext *ctx, arg_r *a)
 420{
 421    TCGv_i64 a0, b0, t0;
 422
 423    if (a->rd == 0) {
 424        /* nop */
 425        return true;
 426    }
 427
 428    a0 = tcg_temp_new_i64();
 429    b0 = tcg_temp_new_i64();
 430    t0 = tcg_temp_new_i64();
 431
 432    gen_load_gpr(a0, a->rs);
 433    gen_load_gpr(b0, a->rt);
 434
 435    gen_load_gpr_hi(t0, a->rt); /* b1 */
 436    tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
 437
 438    gen_load_gpr_hi(t0, a->rs); /* a1 */
 439    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
 440    return true;
 441}
 442
 443static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
 444{
 445    tcg_gen_deposit_i64(dl, b, a, 32, 32);
 446    tcg_gen_shri_i64(b, b, 32);
 447    tcg_gen_deposit_i64(dh, a, b, 0, 32);
 448}
 449
 450static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
 451{
 452    TCGv_i64 ax, bx;
 453
 454    if (a->rd == 0) {
 455        /* nop */
 456        return true;
 457    }
 458
 459    ax = tcg_temp_new_i64();
 460    bx = tcg_temp_new_i64();
 461
 462    gen_load_gpr(ax, a->rs);
 463    gen_load_gpr(bx, a->rt);
 464
 465    /* Lower half */
 466    for (int i = 0; i < 64 / (2 * wlen); i++) {
 467        tcg_gen_deposit_i64(cpu_gpr[a->rd],
 468                            cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
 469        tcg_gen_deposit_i64(cpu_gpr[a->rd],
 470                            cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
 471        tcg_gen_shri_i64(bx, bx, wlen);
 472        tcg_gen_shri_i64(ax, ax, wlen);
 473    }
 474    /* Upper half */
 475    for (int i = 0; i < 64 / (2 * wlen); i++) {
 476        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
 477                            cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
 478        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
 479                            cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
 480        tcg_gen_shri_i64(bx, bx, wlen);
 481        tcg_gen_shri_i64(ax, ax, wlen);
 482    }
 483    return true;
 484}
 485
 486/* Parallel Extend Lower from Byte */
 487static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
 488{
 489    return trans_PEXTLx(ctx, a, 8);
 490}
 491
 492/* Parallel Extend Lower from Halfword */
 493static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
 494{
 495    return trans_PEXTLx(ctx, a, 16);
 496}
 497
 498/* Parallel Extend Lower from Word */
 499static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
 500{
 501    TCGv_i64 ax, bx;
 502
 503    if (a->rd == 0) {
 504        /* nop */
 505        return true;
 506    }
 507
 508    ax = tcg_temp_new_i64();
 509    bx = tcg_temp_new_i64();
 510
 511    gen_load_gpr(ax, a->rs);
 512    gen_load_gpr(bx, a->rt);
 513    gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
 514    return true;
 515}
 516
 517/* Parallel Extend Upper from Word */
 518static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
 519{
 520    TCGv_i64 ax, bx;
 521
 522    if (a->rd == 0) {
 523        /* nop */
 524        return true;
 525    }
 526
 527    ax = tcg_temp_new_i64();
 528    bx = tcg_temp_new_i64();
 529
 530    gen_load_gpr_hi(ax, a->rs);
 531    gen_load_gpr_hi(bx, a->rt);
 532    gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
 533    return true;
 534}
 535
 536/*
 537 *     Others (16 instructions)
 538 *     ------------------------
 539 * PCPYH   rd, rt            Parallel Copy Halfword
 540 * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
 541 * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
 542 * PREVH   rd, rt            Parallel Reverse Halfword
 543 * PINTH   rd, rs, rt        Parallel Interleave Halfword
 544 * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
 545 * PEXEH   rd, rt            Parallel Exchange Even Halfword
 546 * PEXCH   rd, rt            Parallel Exchange Center Halfword
 547 * PEXEW   rd, rt            Parallel Exchange Even Word
 548 * PEXCW   rd, rt            Parallel Exchange Center Word
 549 * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
 550 * MFSA    rd                Move from Shift Amount Register
 551 * MTSA    rs                Move to Shift Amount Register
 552 * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
 553 * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
 554 * PROT3W  rd, rt            Parallel Rotate 3 Words
 555 */
 556
 557/* Parallel Copy Halfword */
 558static bool trans_PCPYH(DisasContext *s, arg_r *a)
 559{
 560    if (a->rd == 0) {
 561        /* nop */
 562        return true;
 563    }
 564
 565    if (a->rt == 0) {
 566        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
 567        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
 568        return true;
 569    }
 570
 571    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
 572    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
 573    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
 574    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
 575
 576    return true;
 577}
 578
 579/* Parallel Copy Lower Doubleword */
 580static bool trans_PCPYLD(DisasContext *s, arg_r *a)
 581{
 582    if (a->rd == 0) {
 583        /* nop */
 584        return true;
 585    }
 586
 587    if (a->rs == 0) {
 588        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
 589    } else {
 590        tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
 591    }
 592
 593    if (a->rt == 0) {
 594        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
 595    } else if (a->rd != a->rt) {
 596        tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
 597    }
 598
 599    return true;
 600}
 601
 602/* Parallel Copy Upper Doubleword */
 603static bool trans_PCPYUD(DisasContext *s, arg_r *a)
 604{
 605    if (a->rd == 0) {
 606        /* nop */
 607        return true;
 608    }
 609
 610    gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
 611
 612    if (a->rt == 0) {
 613        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
 614    } else if (a->rd != a->rt) {
 615        tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
 616    }
 617
 618    return true;
 619}
 620
 621/* Parallel Rotate 3 Words Left */
 622static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
 623{
 624    TCGv_i64 ax;
 625
 626    if (a->rd == 0) {
 627        /* nop */
 628        return true;
 629    }
 630    if (a->rt == 0) {
 631        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
 632        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
 633        return true;
 634    }
 635
 636    ax = tcg_temp_new_i64();
 637
 638    tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
 639    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
 640
 641    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
 642    tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
 643    return true;
 644}
 645