cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

tx79_translate.c (19782B)


      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
    142    tcg_temp_free(bx);
    143    tcg_temp_free(ax);
    144
    145    return true;
    146}
    147
    148/* Parallel Subtract Byte */
    149static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
    150{
    151    return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
    152}
    153
    154/* Parallel Subtract Halfword */
    155static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
    156{
    157    return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
    158}
    159
    160/* Parallel Subtract Word */
    161static bool trans_PSUBW(DisasContext *ctx, arg_r *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 */
    192static bool trans_PAND(DisasContext *ctx, arg_r *a)
    193{
    194    return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
    195}
    196
    197/* Parallel Or */
    198static bool trans_POR(DisasContext *ctx, arg_r *a)
    199{
    200    return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
    201}
    202
    203/* Parallel Exclusive Or */
    204static bool trans_PXOR(DisasContext *ctx, arg_r *a)
    205{
    206    return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
    207}
    208
    209/* Parallel Not Or */
    210static bool trans_PNOR(DisasContext *ctx, arg_r *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
    240static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
    241                                   TCGCond cond, unsigned wlen)
    242{
    243    TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
    244
    245    if (a->rd == 0) {
    246        /* nop */
    247        return true;
    248    }
    249
    250    c0 = tcg_const_tl(0);
    251    c1 = tcg_const_tl(0xffffffff);
    252    ax = tcg_temp_new_i64();
    253    bx = tcg_temp_new_i64();
    254    t0 = tcg_temp_new_i64();
    255    t1 = tcg_temp_new_i64();
    256    t2 = tcg_temp_new_i64();
    257
    258    /* Lower half */
    259    gen_load_gpr(ax, a->rs);
    260    gen_load_gpr(bx, a->rt);
    261    for (int i = 0; i < (64 / wlen); i++) {
    262        tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
    263        tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
    264        tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
    265        tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
    266    }
    267    /* Upper half */
    268    gen_load_gpr_hi(ax, a->rs);
    269    gen_load_gpr_hi(bx, a->rt);
    270    for (int i = 0; i < (64 / wlen); i++) {
    271        tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
    272        tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
    273        tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
    274        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
    275    }
    276
    277    tcg_temp_free(t2);
    278    tcg_temp_free(t1);
    279    tcg_temp_free(t0);
    280    tcg_temp_free(bx);
    281    tcg_temp_free(ax);
    282    tcg_temp_free(c1);
    283    tcg_temp_free(c0);
    284
    285    return true;
    286}
    287
    288/* Parallel Compare for Greater Than Byte */
    289static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
    290{
    291    return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
    292}
    293
    294/* Parallel Compare for Equal Byte */
    295static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
    296{
    297    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
    298}
    299
    300/* Parallel Compare for Greater Than Halfword */
    301static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
    302{
    303    return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
    304}
    305
    306/* Parallel Compare for Equal Halfword */
    307static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
    308{
    309    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
    310}
    311
    312/* Parallel Compare for Greater Than Word */
    313static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
    314{
    315    return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
    316}
    317
    318/* Parallel Compare for Equal Word */
    319static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
    320{
    321    return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
    322}
    323
    324/*
    325 *     LZC (1 instruction)
    326 *     -------------------
    327 * PLZCW   rd, rs            Parallel Leading Zero or One Count Word
    328 */
    329
    330/*
    331 *     Quadword Load and Store (2 instructions)
    332 *     ----------------------------------------
    333 * LQ      rt, offset(base)  Load Quadword
    334 * SQ      rt, offset(base)  Store Quadword
    335 */
    336
    337static bool trans_LQ(DisasContext *ctx, arg_i *a)
    338{
    339    TCGv_i64 t0;
    340    TCGv addr;
    341
    342    if (a->rt == 0) {
    343        /* nop */
    344        return true;
    345    }
    346
    347    t0 = tcg_temp_new_i64();
    348    addr = tcg_temp_new();
    349
    350    gen_base_offset_addr(ctx, addr, a->base, a->offset);
    351    /*
    352     * Clear least-significant four bits of the effective
    353     * address, effectively creating an aligned address.
    354     */
    355    tcg_gen_andi_tl(addr, addr, ~0xf);
    356
    357    /* Lower half */
    358    tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
    359    gen_store_gpr(t0, a->rt);
    360
    361    /* Upper half */
    362    tcg_gen_addi_i64(addr, addr, 8);
    363    tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
    364    gen_store_gpr_hi(t0, a->rt);
    365
    366    tcg_temp_free(t0);
    367    tcg_temp_free(addr);
    368
    369    return true;
    370}
    371
    372static bool trans_SQ(DisasContext *ctx, arg_i *a)
    373{
    374    TCGv_i64 t0 = tcg_temp_new_i64();
    375    TCGv addr = tcg_temp_new();
    376
    377    gen_base_offset_addr(ctx, addr, a->base, a->offset);
    378    /*
    379     * Clear least-significant four bits of the effective
    380     * address, effectively creating an aligned address.
    381     */
    382    tcg_gen_andi_tl(addr, addr, ~0xf);
    383
    384    /* Lower half */
    385    gen_load_gpr(t0, a->rt);
    386    tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
    387
    388    /* Upper half */
    389    tcg_gen_addi_i64(addr, addr, 8);
    390    gen_load_gpr_hi(t0, a->rt);
    391    tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
    392
    393    tcg_temp_free(addr);
    394    tcg_temp_free(t0);
    395
    396    return true;
    397}
    398
    399/*
    400 *     Multiply and Divide (19 instructions)
    401 *     -------------------------------------
    402 * PMULTW  rd, rs, rt        Parallel Multiply Word
    403 * PMULTUW rd, rs, rt        Parallel Multiply Unsigned Word
    404 * PDIVW   rs, rt            Parallel Divide Word
    405 * PDIVUW  rs, rt            Parallel Divide Unsigned Word
    406 * PMADDW  rd, rs, rt        Parallel Multiply-Add Word
    407 * PMADDUW rd, rs, rt        Parallel Multiply-Add Unsigned Word
    408 * PMSUBW  rd, rs, rt        Parallel Multiply-Subtract Word
    409 * PMULTH  rd, rs, rt        Parallel Multiply Halfword
    410 * PMADDH  rd, rs, rt        Parallel Multiply-Add Halfword
    411 * PMSUBH  rd, rs, rt        Parallel Multiply-Subtract Halfword
    412 * PHMADH  rd, rs, rt        Parallel Horizontal Multiply-Add Halfword
    413 * PHMSBH  rd, rs, rt        Parallel Horizontal Multiply-Subtract Halfword
    414 * PDIVBW  rs, rt            Parallel Divide Broadcast Word
    415 * PMFHI   rd                Parallel Move From HI Register
    416 * PMFLO   rd                Parallel Move From LO Register
    417 * PMTHI   rs                Parallel Move To HI Register
    418 * PMTLO   rs                Parallel Move To LO Register
    419 * PMFHL   rd                Parallel Move From HI/LO Register
    420 * PMTHL   rs                Parallel Move To HI/LO Register
    421 */
    422
    423/*
    424 *     Pack/Extend (11 instructions)
    425 *     -----------------------------
    426 * PPAC5   rd, rt            Parallel Pack to 5 bits
    427 * PPACB   rd, rs, rt        Parallel Pack to Byte
    428 * PPACH   rd, rs, rt        Parallel Pack to Halfword
    429 * PPACW   rd, rs, rt        Parallel Pack to Word
    430 * PEXT5   rd, rt            Parallel Extend Upper from 5 bits
    431 * PEXTUB  rd, rs, rt        Parallel Extend Upper from Byte
    432 * PEXTLB  rd, rs, rt        Parallel Extend Lower from Byte
    433 * PEXTUH  rd, rs, rt        Parallel Extend Upper from Halfword
    434 * PEXTLH  rd, rs, rt        Parallel Extend Lower from Halfword
    435 * PEXTUW  rd, rs, rt        Parallel Extend Upper from Word
    436 * PEXTLW  rd, rs, rt        Parallel Extend Lower from Word
    437 */
    438
    439/* Parallel Pack to Word */
    440static bool trans_PPACW(DisasContext *ctx, arg_r *a)
    441{
    442    TCGv_i64 a0, b0, t0;
    443
    444    if (a->rd == 0) {
    445        /* nop */
    446        return true;
    447    }
    448
    449    a0 = tcg_temp_new_i64();
    450    b0 = tcg_temp_new_i64();
    451    t0 = tcg_temp_new_i64();
    452
    453    gen_load_gpr(a0, a->rs);
    454    gen_load_gpr(b0, a->rt);
    455
    456    gen_load_gpr_hi(t0, a->rt); /* b1 */
    457    tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
    458
    459    gen_load_gpr_hi(t0, a->rs); /* a1 */
    460    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
    461
    462    tcg_temp_free(t0);
    463    tcg_temp_free(b0);
    464    tcg_temp_free(a0);
    465
    466    return true;
    467}
    468
    469static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
    470{
    471    tcg_gen_deposit_i64(dl, b, a, 32, 32);
    472    tcg_gen_shri_i64(b, b, 32);
    473    tcg_gen_deposit_i64(dh, a, b, 0, 32);
    474}
    475
    476static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
    477{
    478    TCGv_i64 ax, bx;
    479
    480    if (a->rd == 0) {
    481        /* nop */
    482        return true;
    483    }
    484
    485    ax = tcg_temp_new_i64();
    486    bx = tcg_temp_new_i64();
    487
    488    gen_load_gpr(ax, a->rs);
    489    gen_load_gpr(bx, a->rt);
    490
    491    /* Lower half */
    492    for (int i = 0; i < 64 / (2 * wlen); i++) {
    493        tcg_gen_deposit_i64(cpu_gpr[a->rd],
    494                            cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
    495        tcg_gen_deposit_i64(cpu_gpr[a->rd],
    496                            cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
    497        tcg_gen_shri_i64(bx, bx, wlen);
    498        tcg_gen_shri_i64(ax, ax, wlen);
    499    }
    500    /* Upper half */
    501    for (int i = 0; i < 64 / (2 * wlen); i++) {
    502        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
    503                            cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
    504        tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
    505                            cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
    506        tcg_gen_shri_i64(bx, bx, wlen);
    507        tcg_gen_shri_i64(ax, ax, wlen);
    508    }
    509
    510    tcg_temp_free(bx);
    511    tcg_temp_free(ax);
    512
    513    return true;
    514}
    515
    516/* Parallel Extend Lower from Byte */
    517static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
    518{
    519    return trans_PEXTLx(ctx, a, 8);
    520}
    521
    522/* Parallel Extend Lower from Halfword */
    523static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
    524{
    525    return trans_PEXTLx(ctx, a, 16);
    526}
    527
    528/* Parallel Extend Lower from Word */
    529static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
    530{
    531    TCGv_i64 ax, bx;
    532
    533    if (a->rd == 0) {
    534        /* nop */
    535        return true;
    536    }
    537
    538    ax = tcg_temp_new_i64();
    539    bx = tcg_temp_new_i64();
    540
    541    gen_load_gpr(ax, a->rs);
    542    gen_load_gpr(bx, a->rt);
    543    gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
    544
    545    tcg_temp_free(bx);
    546    tcg_temp_free(ax);
    547
    548    return true;
    549}
    550
    551/* Parallel Extend Upper from Word */
    552static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
    553{
    554    TCGv_i64 ax, bx;
    555
    556    if (a->rd == 0) {
    557        /* nop */
    558        return true;
    559    }
    560
    561    ax = tcg_temp_new_i64();
    562    bx = tcg_temp_new_i64();
    563
    564    gen_load_gpr_hi(ax, a->rs);
    565    gen_load_gpr_hi(bx, a->rt);
    566    gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
    567
    568    tcg_temp_free(bx);
    569    tcg_temp_free(ax);
    570
    571    return true;
    572}
    573
    574/*
    575 *     Others (16 instructions)
    576 *     ------------------------
    577 * PCPYH   rd, rt            Parallel Copy Halfword
    578 * PCPYLD  rd, rs, rt        Parallel Copy Lower Doubleword
    579 * PCPYUD  rd, rs, rt        Parallel Copy Upper Doubleword
    580 * PREVH   rd, rt            Parallel Reverse Halfword
    581 * PINTH   rd, rs, rt        Parallel Interleave Halfword
    582 * PINTEH  rd, rs, rt        Parallel Interleave Even Halfword
    583 * PEXEH   rd, rt            Parallel Exchange Even Halfword
    584 * PEXCH   rd, rt            Parallel Exchange Center Halfword
    585 * PEXEW   rd, rt            Parallel Exchange Even Word
    586 * PEXCW   rd, rt            Parallel Exchange Center Word
    587 * QFSRV   rd, rs, rt        Quadword Funnel Shift Right Variable
    588 * MFSA    rd                Move from Shift Amount Register
    589 * MTSA    rs                Move to Shift Amount Register
    590 * MTSAB   rs, immediate     Move Byte Count to Shift Amount Register
    591 * MTSAH   rs, immediate     Move Halfword Count to Shift Amount Register
    592 * PROT3W  rd, rt            Parallel Rotate 3 Words
    593 */
    594
    595/* Parallel Copy Halfword */
    596static bool trans_PCPYH(DisasContext *s, arg_r *a)
    597{
    598    if (a->rd == 0) {
    599        /* nop */
    600        return true;
    601    }
    602
    603    if (a->rt == 0) {
    604        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
    605        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
    606        return true;
    607    }
    608
    609    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
    610    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
    611    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
    612    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
    613
    614    return true;
    615}
    616
    617/* Parallel Copy Lower Doubleword */
    618static bool trans_PCPYLD(DisasContext *s, arg_r *a)
    619{
    620    if (a->rd == 0) {
    621        /* nop */
    622        return true;
    623    }
    624
    625    if (a->rs == 0) {
    626        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
    627    } else {
    628        tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
    629    }
    630
    631    if (a->rt == 0) {
    632        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
    633    } else if (a->rd != a->rt) {
    634        tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
    635    }
    636
    637    return true;
    638}
    639
    640/* Parallel Copy Upper Doubleword */
    641static bool trans_PCPYUD(DisasContext *s, arg_r *a)
    642{
    643    if (a->rd == 0) {
    644        /* nop */
    645        return true;
    646    }
    647
    648    gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
    649
    650    if (a->rt == 0) {
    651        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
    652    } else if (a->rd != a->rt) {
    653        tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
    654    }
    655
    656    return true;
    657}
    658
    659/* Parallel Rotate 3 Words Left */
    660static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
    661{
    662    TCGv_i64 ax;
    663
    664    if (a->rd == 0) {
    665        /* nop */
    666        return true;
    667    }
    668    if (a->rt == 0) {
    669        tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
    670        tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
    671        return true;
    672    }
    673
    674    ax = tcg_temp_new_i64();
    675
    676    tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
    677    tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
    678
    679    tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
    680    tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
    681
    682    tcg_temp_free(ax);
    683
    684    return true;
    685}