qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

vmx-impl.c.inc (128838B)


      1 /*
      2  * translate/vmx-impl.c
      3  *
      4  * Altivec/VMX translation
      5  */
      6 
      7 /***                      Altivec vector extension                         ***/
      8 /* Altivec registers moves */
      9 
     10 static inline TCGv_ptr gen_avr_ptr(int reg)
     11 {
     12     TCGv_ptr r = tcg_temp_new_ptr();
     13     tcg_gen_addi_ptr(r, cpu_env, avr_full_offset(reg));
     14     return r;
     15 }
     16 
     17 #define GEN_VR_LDX(name, opc2, opc3)                                          \
     18 static void glue(gen_, name)(DisasContext *ctx)                               \
     19 {                                                                             \
     20     TCGv EA;                                                                  \
     21     TCGv_i64 avr;                                                             \
     22     if (unlikely(!ctx->altivec_enabled)) {                                    \
     23         gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
     24         return;                                                               \
     25     }                                                                         \
     26     gen_set_access_type(ctx, ACCESS_INT);                                     \
     27     avr = tcg_temp_new_i64();                                                 \
     28     EA = tcg_temp_new();                                                      \
     29     gen_addr_reg_index(ctx, EA);                                              \
     30     tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
     31     /*                                                                        \
     32      * We only need to swap high and low halves. gen_qemu_ld64_i64            \
     33      * does necessary 64-bit byteswap already.                                \
     34      */                                                                       \
     35     if (ctx->le_mode) {                                                       \
     36         gen_qemu_ld64_i64(ctx, avr, EA);                                      \
     37         set_avr64(rD(ctx->opcode), avr, false);                               \
     38         tcg_gen_addi_tl(EA, EA, 8);                                           \
     39         gen_qemu_ld64_i64(ctx, avr, EA);                                      \
     40         set_avr64(rD(ctx->opcode), avr, true);                                \
     41     } else {                                                                  \
     42         gen_qemu_ld64_i64(ctx, avr, EA);                                      \
     43         set_avr64(rD(ctx->opcode), avr, true);                                \
     44         tcg_gen_addi_tl(EA, EA, 8);                                           \
     45         gen_qemu_ld64_i64(ctx, avr, EA);                                      \
     46         set_avr64(rD(ctx->opcode), avr, false);                               \
     47     }                                                                         \
     48     tcg_temp_free(EA);                                                        \
     49     tcg_temp_free_i64(avr);                                                   \
     50 }
     51 
     52 #define GEN_VR_STX(name, opc2, opc3)                                          \
     53 static void gen_st##name(DisasContext *ctx)                                   \
     54 {                                                                             \
     55     TCGv EA;                                                                  \
     56     TCGv_i64 avr;                                                             \
     57     if (unlikely(!ctx->altivec_enabled)) {                                    \
     58         gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
     59         return;                                                               \
     60     }                                                                         \
     61     gen_set_access_type(ctx, ACCESS_INT);                                     \
     62     avr = tcg_temp_new_i64();                                                 \
     63     EA = tcg_temp_new();                                                      \
     64     gen_addr_reg_index(ctx, EA);                                              \
     65     tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
     66     /*                                                                        \
     67      * We only need to swap high and low halves. gen_qemu_st64_i64            \
     68      * does necessary 64-bit byteswap already.                                \
     69      */                                                                       \
     70     if (ctx->le_mode) {                                                       \
     71         get_avr64(avr, rD(ctx->opcode), false);                               \
     72         gen_qemu_st64_i64(ctx, avr, EA);                                      \
     73         tcg_gen_addi_tl(EA, EA, 8);                                           \
     74         get_avr64(avr, rD(ctx->opcode), true);                                \
     75         gen_qemu_st64_i64(ctx, avr, EA);                                      \
     76     } else {                                                                  \
     77         get_avr64(avr, rD(ctx->opcode), true);                                \
     78         gen_qemu_st64_i64(ctx, avr, EA);                                      \
     79         tcg_gen_addi_tl(EA, EA, 8);                                           \
     80         get_avr64(avr, rD(ctx->opcode), false);                               \
     81         gen_qemu_st64_i64(ctx, avr, EA);                                      \
     82     }                                                                         \
     83     tcg_temp_free(EA);                                                        \
     84     tcg_temp_free_i64(avr);                                                   \
     85 }
     86 
     87 #define GEN_VR_LVE(name, opc2, opc3, size)                              \
     88 static void gen_lve##name(DisasContext *ctx)                            \
     89     {                                                                   \
     90         TCGv EA;                                                        \
     91         TCGv_ptr rs;                                                    \
     92         if (unlikely(!ctx->altivec_enabled)) {                          \
     93             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
     94             return;                                                     \
     95         }                                                               \
     96         gen_set_access_type(ctx, ACCESS_INT);                           \
     97         EA = tcg_temp_new();                                            \
     98         gen_addr_reg_index(ctx, EA);                                    \
     99         if (size > 1) {                                                 \
    100             tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
    101         }                                                               \
    102         rs = gen_avr_ptr(rS(ctx->opcode));                              \
    103         gen_helper_lve##name(cpu_env, rs, EA);                          \
    104         tcg_temp_free(EA);                                              \
    105         tcg_temp_free_ptr(rs);                                          \
    106     }
    107 
    108 #define GEN_VR_STVE(name, opc2, opc3, size)                             \
    109 static void gen_stve##name(DisasContext *ctx)                           \
    110     {                                                                   \
    111         TCGv EA;                                                        \
    112         TCGv_ptr rs;                                                    \
    113         if (unlikely(!ctx->altivec_enabled)) {                          \
    114             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
    115             return;                                                     \
    116         }                                                               \
    117         gen_set_access_type(ctx, ACCESS_INT);                           \
    118         EA = tcg_temp_new();                                            \
    119         gen_addr_reg_index(ctx, EA);                                    \
    120         if (size > 1) {                                                 \
    121             tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
    122         }                                                               \
    123         rs = gen_avr_ptr(rS(ctx->opcode));                              \
    124         gen_helper_stve##name(cpu_env, rs, EA);                         \
    125         tcg_temp_free(EA);                                              \
    126         tcg_temp_free_ptr(rs);                                          \
    127     }
    128 
    129 GEN_VR_LDX(lvx, 0x07, 0x03);
    130 /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
    131 GEN_VR_LDX(lvxl, 0x07, 0x0B);
    132 
    133 GEN_VR_LVE(bx, 0x07, 0x00, 1);
    134 GEN_VR_LVE(hx, 0x07, 0x01, 2);
    135 GEN_VR_LVE(wx, 0x07, 0x02, 4);
    136 
    137 GEN_VR_STX(svx, 0x07, 0x07);
    138 /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
    139 GEN_VR_STX(svxl, 0x07, 0x0F);
    140 
    141 GEN_VR_STVE(bx, 0x07, 0x04, 1);
    142 GEN_VR_STVE(hx, 0x07, 0x05, 2);
    143 GEN_VR_STVE(wx, 0x07, 0x06, 4);
    144 
    145 static void gen_mfvscr(DisasContext *ctx)
    146 {
    147     TCGv_i32 t;
    148     TCGv_i64 avr;
    149     if (unlikely(!ctx->altivec_enabled)) {
    150         gen_exception(ctx, POWERPC_EXCP_VPU);
    151         return;
    152     }
    153     avr = tcg_temp_new_i64();
    154     tcg_gen_movi_i64(avr, 0);
    155     set_avr64(rD(ctx->opcode), avr, true);
    156     t = tcg_temp_new_i32();
    157     gen_helper_mfvscr(t, cpu_env);
    158     tcg_gen_extu_i32_i64(avr, t);
    159     set_avr64(rD(ctx->opcode), avr, false);
    160     tcg_temp_free_i32(t);
    161     tcg_temp_free_i64(avr);
    162 }
    163 
    164 static void gen_mtvscr(DisasContext *ctx)
    165 {
    166     TCGv_i32 val;
    167     int bofs;
    168 
    169     if (unlikely(!ctx->altivec_enabled)) {
    170         gen_exception(ctx, POWERPC_EXCP_VPU);
    171         return;
    172     }
    173 
    174     val = tcg_temp_new_i32();
    175     bofs = avr_full_offset(rB(ctx->opcode));
    176 #if HOST_BIG_ENDIAN
    177     bofs += 3 * 4;
    178 #endif
    179 
    180     tcg_gen_ld_i32(val, cpu_env, bofs);
    181     gen_helper_mtvscr(cpu_env, val);
    182     tcg_temp_free_i32(val);
    183 }
    184 
    185 #define GEN_VX_VMUL10(name, add_cin, ret_carry)                         \
    186 static void glue(gen_, name)(DisasContext *ctx)                         \
    187 {                                                                       \
    188     TCGv_i64 t0;                                                        \
    189     TCGv_i64 t1;                                                        \
    190     TCGv_i64 t2;                                                        \
    191     TCGv_i64 avr;                                                       \
    192     TCGv_i64 ten, z;                                                    \
    193                                                                         \
    194     if (unlikely(!ctx->altivec_enabled)) {                              \
    195         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    196         return;                                                         \
    197     }                                                                   \
    198                                                                         \
    199     t0 = tcg_temp_new_i64();                                            \
    200     t1 = tcg_temp_new_i64();                                            \
    201     t2 = tcg_temp_new_i64();                                            \
    202     avr = tcg_temp_new_i64();                                           \
    203     ten = tcg_const_i64(10);                                            \
    204     z = tcg_const_i64(0);                                               \
    205                                                                         \
    206     if (add_cin) {                                                      \
    207         get_avr64(avr, rA(ctx->opcode), false);                         \
    208         tcg_gen_mulu2_i64(t0, t1, avr, ten);                            \
    209         get_avr64(avr, rB(ctx->opcode), false);                         \
    210         tcg_gen_andi_i64(t2, avr, 0xF);                                 \
    211         tcg_gen_add2_i64(avr, t2, t0, t1, t2, z);                       \
    212         set_avr64(rD(ctx->opcode), avr, false);                         \
    213     } else {                                                            \
    214         get_avr64(avr, rA(ctx->opcode), false);                         \
    215         tcg_gen_mulu2_i64(avr, t2, avr, ten);                           \
    216         set_avr64(rD(ctx->opcode), avr, false);                         \
    217     }                                                                   \
    218                                                                         \
    219     if (ret_carry) {                                                    \
    220         get_avr64(avr, rA(ctx->opcode), true);                          \
    221         tcg_gen_mulu2_i64(t0, t1, avr, ten);                            \
    222         tcg_gen_add2_i64(t0, avr, t0, t1, t2, z);                       \
    223         set_avr64(rD(ctx->opcode), avr, false);                         \
    224         set_avr64(rD(ctx->opcode), z, true);                            \
    225     } else {                                                            \
    226         get_avr64(avr, rA(ctx->opcode), true);                          \
    227         tcg_gen_mul_i64(t0, avr, ten);                                  \
    228         tcg_gen_add_i64(avr, t0, t2);                                   \
    229         set_avr64(rD(ctx->opcode), avr, true);                          \
    230     }                                                                   \
    231                                                                         \
    232     tcg_temp_free_i64(t0);                                              \
    233     tcg_temp_free_i64(t1);                                              \
    234     tcg_temp_free_i64(t2);                                              \
    235     tcg_temp_free_i64(avr);                                             \
    236     tcg_temp_free_i64(ten);                                             \
    237     tcg_temp_free_i64(z);                                               \
    238 }                                                                       \
    239 
    240 GEN_VX_VMUL10(vmul10uq, 0, 0);
    241 GEN_VX_VMUL10(vmul10euq, 1, 0);
    242 GEN_VX_VMUL10(vmul10cuq, 0, 1);
    243 GEN_VX_VMUL10(vmul10ecuq, 1, 1);
    244 
    245 #define GEN_VXFORM_V(name, vece, tcg_op, opc2, opc3)                    \
    246 static void glue(gen_, name)(DisasContext *ctx)                         \
    247 {                                                                       \
    248     if (unlikely(!ctx->altivec_enabled)) {                              \
    249         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    250         return;                                                         \
    251     }                                                                   \
    252                                                                         \
    253     tcg_op(vece,                                                        \
    254            avr_full_offset(rD(ctx->opcode)),                            \
    255            avr_full_offset(rA(ctx->opcode)),                            \
    256            avr_full_offset(rB(ctx->opcode)),                            \
    257            16, 16);                                                     \
    258 }
    259 
    260 /* Logical operations */
    261 GEN_VXFORM_V(vand, MO_64, tcg_gen_gvec_and, 2, 16);
    262 GEN_VXFORM_V(vandc, MO_64, tcg_gen_gvec_andc, 2, 17);
    263 GEN_VXFORM_V(vor, MO_64, tcg_gen_gvec_or, 2, 18);
    264 GEN_VXFORM_V(vxor, MO_64, tcg_gen_gvec_xor, 2, 19);
    265 GEN_VXFORM_V(vnor, MO_64, tcg_gen_gvec_nor, 2, 20);
    266 GEN_VXFORM_V(veqv, MO_64, tcg_gen_gvec_eqv, 2, 26);
    267 GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
    268 GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
    269 
    270 #define GEN_VXFORM(name, opc2, opc3)                                    \
    271 static void glue(gen_, name)(DisasContext *ctx)                         \
    272 {                                                                       \
    273     TCGv_ptr ra, rb, rd;                                                \
    274     if (unlikely(!ctx->altivec_enabled)) {                              \
    275         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    276         return;                                                         \
    277     }                                                                   \
    278     ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    279     rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    280     rd = gen_avr_ptr(rD(ctx->opcode));                                  \
    281     gen_helper_##name(rd, ra, rb);                                      \
    282     tcg_temp_free_ptr(ra);                                              \
    283     tcg_temp_free_ptr(rb);                                              \
    284     tcg_temp_free_ptr(rd);                                              \
    285 }
    286 
    287 #define GEN_VXFORM_TRANS(name, opc2, opc3)                              \
    288 static void glue(gen_, name)(DisasContext *ctx)                         \
    289 {                                                                       \
    290     if (unlikely(!ctx->altivec_enabled)) {                              \
    291         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    292         return;                                                         \
    293     }                                                                   \
    294     trans_##name(ctx);                                                  \
    295 }
    296 
    297 #define GEN_VXFORM_ENV(name, opc2, opc3)                                \
    298 static void glue(gen_, name)(DisasContext *ctx)                         \
    299 {                                                                       \
    300     TCGv_ptr ra, rb, rd;                                                \
    301     if (unlikely(!ctx->altivec_enabled)) {                              \
    302         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    303         return;                                                         \
    304     }                                                                   \
    305     ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    306     rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    307     rd = gen_avr_ptr(rD(ctx->opcode));                                  \
    308     gen_helper_##name(cpu_env, rd, ra, rb);                             \
    309     tcg_temp_free_ptr(ra);                                              \
    310     tcg_temp_free_ptr(rb);                                              \
    311     tcg_temp_free_ptr(rd);                                              \
    312 }
    313 
    314 #define GEN_VXFORM3(name, opc2, opc3)                                   \
    315 static void glue(gen_, name)(DisasContext *ctx)                         \
    316 {                                                                       \
    317     TCGv_ptr ra, rb, rc, rd;                                            \
    318     if (unlikely(!ctx->altivec_enabled)) {                              \
    319         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    320         return;                                                         \
    321     }                                                                   \
    322     ra = gen_avr_ptr(rA(ctx->opcode));                                  \
    323     rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    324     rc = gen_avr_ptr(rC(ctx->opcode));                                  \
    325     rd = gen_avr_ptr(rD(ctx->opcode));                                  \
    326     gen_helper_##name(rd, ra, rb, rc);                                  \
    327     tcg_temp_free_ptr(ra);                                              \
    328     tcg_temp_free_ptr(rb);                                              \
    329     tcg_temp_free_ptr(rc);                                              \
    330     tcg_temp_free_ptr(rd);                                              \
    331 }
    332 
    333 /*
    334  * Support for Altivec instruction pairs that use bit 31 (Rc) as
    335  * an opcode bit.  In general, these pairs come from different
    336  * versions of the ISA, so we must also support a pair of flags for
    337  * each instruction.
    338  */
    339 #define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)          \
    340 static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
    341 {                                                                      \
    342     if ((Rc(ctx->opcode) == 0) &&                                      \
    343         ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
    344         gen_##name0(ctx);                                              \
    345     } else if ((Rc(ctx->opcode) == 1) &&                               \
    346         ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
    347         gen_##name1(ctx);                                              \
    348     } else {                                                           \
    349         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
    350     }                                                                  \
    351 }
    352 
    353 /*
    354  * We use this macro if one instruction is realized with direct
    355  * translation, and second one with helper.
    356  */
    357 #define GEN_VXFORM_TRANS_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)\
    358 static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
    359 {                                                                      \
    360     if ((Rc(ctx->opcode) == 0) &&                                      \
    361         ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
    362         if (unlikely(!ctx->altivec_enabled)) {                         \
    363             gen_exception(ctx, POWERPC_EXCP_VPU);                      \
    364             return;                                                    \
    365         }                                                              \
    366         trans_##name0(ctx);                                            \
    367     } else if ((Rc(ctx->opcode) == 1) &&                               \
    368         ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
    369         gen_##name1(ctx);                                              \
    370     } else {                                                           \
    371         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
    372     }                                                                  \
    373 }
    374 
    375 /* Adds support to provide invalid mask */
    376 #define GEN_VXFORM_DUAL_EXT(name0, flg0, flg2_0, inval0,                \
    377                             name1, flg1, flg2_1, inval1)                \
    378 static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
    379 {                                                                       \
    380     if ((Rc(ctx->opcode) == 0) &&                                       \
    381         ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0)) &&  \
    382         !(ctx->opcode & inval0)) {                                      \
    383         gen_##name0(ctx);                                               \
    384     } else if ((Rc(ctx->opcode) == 1) &&                                \
    385                ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1)) && \
    386                !(ctx->opcode & inval1)) {                               \
    387         gen_##name1(ctx);                                               \
    388     } else {                                                            \
    389         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);             \
    390     }                                                                   \
    391 }
    392 
    393 #define GEN_VXFORM_HETRO(name, opc2, opc3)                              \
    394 static void glue(gen_, name)(DisasContext *ctx)                         \
    395 {                                                                       \
    396     TCGv_ptr rb;                                                        \
    397     if (unlikely(!ctx->altivec_enabled)) {                              \
    398         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
    399         return;                                                         \
    400     }                                                                   \
    401     rb = gen_avr_ptr(rB(ctx->opcode));                                  \
    402     gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], rb); \
    403     tcg_temp_free_ptr(rb);                                              \
    404 }
    405 
    406 GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
    407 GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0,       \
    408                     vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
    409 GEN_VXFORM_V(vadduhm, MO_16, tcg_gen_gvec_add, 0, 1);
    410 GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE,  \
    411                 vmul10ecuq, PPC_NONE, PPC2_ISA300)
    412 GEN_VXFORM_V(vadduwm, MO_32, tcg_gen_gvec_add, 0, 2);
    413 GEN_VXFORM_V(vaddudm, MO_64, tcg_gen_gvec_add, 0, 3);
    414 GEN_VXFORM_V(vsububm, MO_8, tcg_gen_gvec_sub, 0, 16);
    415 GEN_VXFORM_V(vsubuhm, MO_16, tcg_gen_gvec_sub, 0, 17);
    416 GEN_VXFORM_V(vsubuwm, MO_32, tcg_gen_gvec_sub, 0, 18);
    417 GEN_VXFORM_V(vsubudm, MO_64, tcg_gen_gvec_sub, 0, 19);
    418 GEN_VXFORM_V(vmaxub, MO_8, tcg_gen_gvec_umax, 1, 0);
    419 GEN_VXFORM_V(vmaxuh, MO_16, tcg_gen_gvec_umax, 1, 1);
    420 GEN_VXFORM_V(vmaxuw, MO_32, tcg_gen_gvec_umax, 1, 2);
    421 GEN_VXFORM_V(vmaxud, MO_64, tcg_gen_gvec_umax, 1, 3);
    422 GEN_VXFORM_V(vmaxsb, MO_8, tcg_gen_gvec_smax, 1, 4);
    423 GEN_VXFORM_V(vmaxsh, MO_16, tcg_gen_gvec_smax, 1, 5);
    424 GEN_VXFORM_V(vmaxsw, MO_32, tcg_gen_gvec_smax, 1, 6);
    425 GEN_VXFORM_V(vmaxsd, MO_64, tcg_gen_gvec_smax, 1, 7);
    426 GEN_VXFORM_V(vminub, MO_8, tcg_gen_gvec_umin, 1, 8);
    427 GEN_VXFORM_V(vminuh, MO_16, tcg_gen_gvec_umin, 1, 9);
    428 GEN_VXFORM_V(vminuw, MO_32, tcg_gen_gvec_umin, 1, 10);
    429 GEN_VXFORM_V(vminud, MO_64, tcg_gen_gvec_umin, 1, 11);
    430 GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
    431 GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
    432 GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
    433 GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
    434 GEN_VXFORM(vmrghb, 6, 0);
    435 GEN_VXFORM(vmrghh, 6, 1);
    436 GEN_VXFORM(vmrghw, 6, 2);
    437 GEN_VXFORM(vmrglb, 6, 4);
    438 GEN_VXFORM(vmrglh, 6, 5);
    439 GEN_VXFORM(vmrglw, 6, 6);
    440 
    441 static void trans_vmrgew(DisasContext *ctx)
    442 {
    443     int VT = rD(ctx->opcode);
    444     int VA = rA(ctx->opcode);
    445     int VB = rB(ctx->opcode);
    446     TCGv_i64 tmp = tcg_temp_new_i64();
    447     TCGv_i64 avr = tcg_temp_new_i64();
    448 
    449     get_avr64(avr, VB, true);
    450     tcg_gen_shri_i64(tmp, avr, 32);
    451     get_avr64(avr, VA, true);
    452     tcg_gen_deposit_i64(avr, avr, tmp, 0, 32);
    453     set_avr64(VT, avr, true);
    454 
    455     get_avr64(avr, VB, false);
    456     tcg_gen_shri_i64(tmp, avr, 32);
    457     get_avr64(avr, VA, false);
    458     tcg_gen_deposit_i64(avr, avr, tmp, 0, 32);
    459     set_avr64(VT, avr, false);
    460 
    461     tcg_temp_free_i64(tmp);
    462     tcg_temp_free_i64(avr);
    463 }
    464 
    465 static void trans_vmrgow(DisasContext *ctx)
    466 {
    467     int VT = rD(ctx->opcode);
    468     int VA = rA(ctx->opcode);
    469     int VB = rB(ctx->opcode);
    470     TCGv_i64 t0 = tcg_temp_new_i64();
    471     TCGv_i64 t1 = tcg_temp_new_i64();
    472     TCGv_i64 avr = tcg_temp_new_i64();
    473 
    474     get_avr64(t0, VB, true);
    475     get_avr64(t1, VA, true);
    476     tcg_gen_deposit_i64(avr, t0, t1, 32, 32);
    477     set_avr64(VT, avr, true);
    478 
    479     get_avr64(t0, VB, false);
    480     get_avr64(t1, VA, false);
    481     tcg_gen_deposit_i64(avr, t0, t1, 32, 32);
    482     set_avr64(VT, avr, false);
    483 
    484     tcg_temp_free_i64(t0);
    485     tcg_temp_free_i64(t1);
    486     tcg_temp_free_i64(avr);
    487 }
    488 
    489 /*
    490  * lvsl VRT,RA,RB - Load Vector for Shift Left
    491  *
    492  * Let the EA be the sum (rA|0)+(rB). Let sh=EA[28–31].
    493  * Let X be the 32-byte value 0x00 || 0x01 || 0x02 || ... || 0x1E || 0x1F.
    494  * Bytes sh:sh+15 of X are placed into vD.
    495  */
    496 static void trans_lvsl(DisasContext *ctx)
    497 {
    498     int VT = rD(ctx->opcode);
    499     TCGv_i64 result = tcg_temp_new_i64();
    500     TCGv_i64 sh = tcg_temp_new_i64();
    501     TCGv EA = tcg_temp_new();
    502 
    503     /* Get sh(from description) by anding EA with 0xf. */
    504     gen_addr_reg_index(ctx, EA);
    505     tcg_gen_extu_tl_i64(sh, EA);
    506     tcg_gen_andi_i64(sh, sh, 0xfULL);
    507 
    508     /*
    509      * Create bytes sh:sh+7 of X(from description) and place them in
    510      * higher doubleword of vD.
    511      */
    512     tcg_gen_muli_i64(sh, sh, 0x0101010101010101ULL);
    513     tcg_gen_addi_i64(result, sh, 0x0001020304050607ull);
    514     set_avr64(VT, result, true);
    515     /*
    516      * Create bytes sh+8:sh+15 of X(from description) and place them in
    517      * lower doubleword of vD.
    518      */
    519     tcg_gen_addi_i64(result, sh, 0x08090a0b0c0d0e0fULL);
    520     set_avr64(VT, result, false);
    521 
    522     tcg_temp_free_i64(result);
    523     tcg_temp_free_i64(sh);
    524     tcg_temp_free(EA);
    525 }
    526 
    527 /*
    528  * lvsr VRT,RA,RB - Load Vector for Shift Right
    529  *
    530  * Let the EA be the sum (rA|0)+(rB). Let sh=EA[28–31].
    531  * Let X be the 32-byte value 0x00 || 0x01 || 0x02 || ... || 0x1E || 0x1F.
    532  * Bytes (16-sh):(31-sh) of X are placed into vD.
    533  */
    534 static void trans_lvsr(DisasContext *ctx)
    535 {
    536     int VT = rD(ctx->opcode);
    537     TCGv_i64 result = tcg_temp_new_i64();
    538     TCGv_i64 sh = tcg_temp_new_i64();
    539     TCGv EA = tcg_temp_new();
    540 
    541 
    542     /* Get sh(from description) by anding EA with 0xf. */
    543     gen_addr_reg_index(ctx, EA);
    544     tcg_gen_extu_tl_i64(sh, EA);
    545     tcg_gen_andi_i64(sh, sh, 0xfULL);
    546 
    547     /*
    548      * Create bytes (16-sh):(23-sh) of X(from description) and place them in
    549      * higher doubleword of vD.
    550      */
    551     tcg_gen_muli_i64(sh, sh, 0x0101010101010101ULL);
    552     tcg_gen_subfi_i64(result, 0x1011121314151617ULL, sh);
    553     set_avr64(VT, result, true);
    554     /*
    555      * Create bytes (24-sh):(32-sh) of X(from description) and place them in
    556      * lower doubleword of vD.
    557      */
    558     tcg_gen_subfi_i64(result, 0x18191a1b1c1d1e1fULL, sh);
    559     set_avr64(VT, result, false);
    560 
    561     tcg_temp_free_i64(result);
    562     tcg_temp_free_i64(sh);
    563     tcg_temp_free(EA);
    564 }
    565 
    566 /*
    567  * vsl VRT,VRA,VRB - Vector Shift Left
    568  *
    569  * Shifting left 128 bit value of vA by value specified in bits 125-127 of vB.
    570  * Lowest 3 bits in each byte element of register vB must be identical or
    571  * result is undefined.
    572  */
    573 static void trans_vsl(DisasContext *ctx)
    574 {
    575     int VT = rD(ctx->opcode);
    576     int VA = rA(ctx->opcode);
    577     int VB = rB(ctx->opcode);
    578     TCGv_i64 avr = tcg_temp_new_i64();
    579     TCGv_i64 sh = tcg_temp_new_i64();
    580     TCGv_i64 carry = tcg_temp_new_i64();
    581     TCGv_i64 tmp = tcg_temp_new_i64();
    582 
    583     /* Place bits 125-127 of vB in 'sh'. */
    584     get_avr64(avr, VB, false);
    585     tcg_gen_andi_i64(sh, avr, 0x07ULL);
    586 
    587     /*
    588      * Save highest 'sh' bits of lower doubleword element of vA in variable
    589      * 'carry' and perform shift on lower doubleword.
    590      */
    591     get_avr64(avr, VA, false);
    592     tcg_gen_subfi_i64(tmp, 32, sh);
    593     tcg_gen_shri_i64(carry, avr, 32);
    594     tcg_gen_shr_i64(carry, carry, tmp);
    595     tcg_gen_shl_i64(avr, avr, sh);
    596     set_avr64(VT, avr, false);
    597 
    598     /*
    599      * Perform shift on higher doubleword element of vA and replace lowest
    600      * 'sh' bits with 'carry'.
    601      */
    602     get_avr64(avr, VA, true);
    603     tcg_gen_shl_i64(avr, avr, sh);
    604     tcg_gen_or_i64(avr, avr, carry);
    605     set_avr64(VT, avr, true);
    606 
    607     tcg_temp_free_i64(avr);
    608     tcg_temp_free_i64(sh);
    609     tcg_temp_free_i64(carry);
    610     tcg_temp_free_i64(tmp);
    611 }
    612 
    613 /*
    614  * vsr VRT,VRA,VRB - Vector Shift Right
    615  *
    616  * Shifting right 128 bit value of vA by value specified in bits 125-127 of vB.
    617  * Lowest 3 bits in each byte element of register vB must be identical or
    618  * result is undefined.
    619  */
    620 static void trans_vsr(DisasContext *ctx)
    621 {
    622     int VT = rD(ctx->opcode);
    623     int VA = rA(ctx->opcode);
    624     int VB = rB(ctx->opcode);
    625     TCGv_i64 avr = tcg_temp_new_i64();
    626     TCGv_i64 sh = tcg_temp_new_i64();
    627     TCGv_i64 carry = tcg_temp_new_i64();
    628     TCGv_i64 tmp = tcg_temp_new_i64();
    629 
    630     /* Place bits 125-127 of vB in 'sh'. */
    631     get_avr64(avr, VB, false);
    632     tcg_gen_andi_i64(sh, avr, 0x07ULL);
    633 
    634     /*
    635      * Save lowest 'sh' bits of higher doubleword element of vA in variable
    636      * 'carry' and perform shift on higher doubleword.
    637      */
    638     get_avr64(avr, VA, true);
    639     tcg_gen_subfi_i64(tmp, 32, sh);
    640     tcg_gen_shli_i64(carry, avr, 32);
    641     tcg_gen_shl_i64(carry, carry, tmp);
    642     tcg_gen_shr_i64(avr, avr, sh);
    643     set_avr64(VT, avr, true);
    644     /*
    645      * Perform shift on lower doubleword element of vA and replace highest
    646      * 'sh' bits with 'carry'.
    647      */
    648     get_avr64(avr, VA, false);
    649     tcg_gen_shr_i64(avr, avr, sh);
    650     tcg_gen_or_i64(avr, avr, carry);
    651     set_avr64(VT, avr, false);
    652 
    653     tcg_temp_free_i64(avr);
    654     tcg_temp_free_i64(sh);
    655     tcg_temp_free_i64(carry);
    656     tcg_temp_free_i64(tmp);
    657 }
    658 
    659 /*
    660  * vgbbd VRT,VRB - Vector Gather Bits by Bytes by Doubleword
    661  *
    662  * All ith bits (i in range 1 to 8) of each byte of doubleword element in source
    663  * register are concatenated and placed into ith byte of appropriate doubleword
    664  * element in destination register.
    665  *
    666  * Following solution is done for both doubleword elements of source register
    667  * in parallel, in order to reduce the number of instructions needed(that's why
    668  * arrays are used):
    669  * First, both doubleword elements of source register vB are placed in
    670  * appropriate element of array avr. Bits are gathered in 2x8 iterations(2 for
    671  * loops). In first iteration bit 1 of byte 1, bit 2 of byte 2,... bit 8 of
    672  * byte 8 are in their final spots so avr[i], i={0,1} can be and-ed with
    673  * tcg_mask. For every following iteration, both avr[i] and tcg_mask variables
    674  * have to be shifted right for 7 and 8 places, respectively, in order to get
    675  * bit 1 of byte 2, bit 2 of byte 3.. bit 7 of byte 8 in their final spots so
    676  * shifted avr values(saved in tmp) can be and-ed with new value of tcg_mask...
    677  * After first 8 iteration(first loop), all the first bits are in their final
    678  * places, all second bits but second bit from eight byte are in their places...
    679  * only 1 eight bit from eight byte is in it's place). In second loop we do all
    680  * operations symmetrically, in order to get other half of bits in their final
    681  * spots. Results for first and second doubleword elements are saved in
    682  * result[0] and result[1] respectively. In the end those results are saved in
    683  * appropriate doubleword element of destination register vD.
    684  */
    685 static void trans_vgbbd(DisasContext *ctx)
    686 {
    687     int VT = rD(ctx->opcode);
    688     int VB = rB(ctx->opcode);
    689     TCGv_i64 tmp = tcg_temp_new_i64();
    690     uint64_t mask = 0x8040201008040201ULL;
    691     int i, j;
    692 
    693     TCGv_i64 result[2];
    694     result[0] = tcg_temp_new_i64();
    695     result[1] = tcg_temp_new_i64();
    696     TCGv_i64 avr[2];
    697     avr[0] = tcg_temp_new_i64();
    698     avr[1] = tcg_temp_new_i64();
    699     TCGv_i64 tcg_mask = tcg_temp_new_i64();
    700 
    701     tcg_gen_movi_i64(tcg_mask, mask);
    702     for (j = 0; j < 2; j++) {
    703         get_avr64(avr[j], VB, j);
    704         tcg_gen_and_i64(result[j], avr[j], tcg_mask);
    705     }
    706     for (i = 1; i < 8; i++) {
    707         tcg_gen_movi_i64(tcg_mask, mask >> (i * 8));
    708         for (j = 0; j < 2; j++) {
    709             tcg_gen_shri_i64(tmp, avr[j], i * 7);
    710             tcg_gen_and_i64(tmp, tmp, tcg_mask);
    711             tcg_gen_or_i64(result[j], result[j], tmp);
    712         }
    713     }
    714     for (i = 1; i < 8; i++) {
    715         tcg_gen_movi_i64(tcg_mask, mask << (i * 8));
    716         for (j = 0; j < 2; j++) {
    717             tcg_gen_shli_i64(tmp, avr[j], i * 7);
    718             tcg_gen_and_i64(tmp, tmp, tcg_mask);
    719             tcg_gen_or_i64(result[j], result[j], tmp);
    720         }
    721     }
    722     for (j = 0; j < 2; j++) {
    723         set_avr64(VT, result[j], j);
    724     }
    725 
    726     tcg_temp_free_i64(tmp);
    727     tcg_temp_free_i64(tcg_mask);
    728     tcg_temp_free_i64(result[0]);
    729     tcg_temp_free_i64(result[1]);
    730     tcg_temp_free_i64(avr[0]);
    731     tcg_temp_free_i64(avr[1]);
    732 }
    733 
    734 /*
    735  * vclzw VRT,VRB - Vector Count Leading Zeros Word
    736  *
    737  * Counting the number of leading zero bits of each word element in source
    738  * register and placing result in appropriate word element of destination
    739  * register.
    740  */
    741 static void trans_vclzw(DisasContext *ctx)
    742 {
    743     int VT = rD(ctx->opcode);
    744     int VB = rB(ctx->opcode);
    745     TCGv_i32 tmp = tcg_temp_new_i32();
    746     int i;
    747 
    748     /* Perform count for every word element using tcg_gen_clzi_i32. */
    749     for (i = 0; i < 4; i++) {
    750         tcg_gen_ld_i32(tmp, cpu_env,
    751             offsetof(CPUPPCState, vsr[32 + VB].u64[0]) + i * 4);
    752         tcg_gen_clzi_i32(tmp, tmp, 32);
    753         tcg_gen_st_i32(tmp, cpu_env,
    754             offsetof(CPUPPCState, vsr[32 + VT].u64[0]) + i * 4);
    755     }
    756 
    757     tcg_temp_free_i32(tmp);
    758 }
    759 
    760 /*
    761  * vclzd VRT,VRB - Vector Count Leading Zeros Doubleword
    762  *
    763  * Counting the number of leading zero bits of each doubleword element in source
    764  * register and placing result in appropriate doubleword element of destination
    765  * register.
    766  */
    767 static void trans_vclzd(DisasContext *ctx)
    768 {
    769     int VT = rD(ctx->opcode);
    770     int VB = rB(ctx->opcode);
    771     TCGv_i64 avr = tcg_temp_new_i64();
    772 
    773     /* high doubleword */
    774     get_avr64(avr, VB, true);
    775     tcg_gen_clzi_i64(avr, avr, 64);
    776     set_avr64(VT, avr, true);
    777 
    778     /* low doubleword */
    779     get_avr64(avr, VB, false);
    780     tcg_gen_clzi_i64(avr, avr, 64);
    781     set_avr64(VT, avr, false);
    782 
    783     tcg_temp_free_i64(avr);
    784 }
    785 
    786 GEN_VXFORM_V(vmuluwm, MO_32, tcg_gen_gvec_mul, 4, 2);
    787 GEN_VXFORM(vsrv, 2, 28);
    788 GEN_VXFORM(vslv, 2, 29);
    789 GEN_VXFORM(vslo, 6, 16);
    790 GEN_VXFORM(vsro, 6, 17);
    791 
    792 static bool do_vector_gvec3_VX(DisasContext *ctx, arg_VX *a, int vece,
    793                                void (*gen_gvec)(unsigned, uint32_t, uint32_t,
    794                                                 uint32_t, uint32_t, uint32_t))
    795 {
    796     REQUIRE_VECTOR(ctx);
    797 
    798     gen_gvec(vece, avr_full_offset(a->vrt), avr_full_offset(a->vra),
    799              avr_full_offset(a->vrb), 16, 16);
    800 
    801     return true;
    802 }
    803 
    804 TRANS_FLAGS(ALTIVEC, VSLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shlv);
    805 TRANS_FLAGS(ALTIVEC, VSLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shlv);
    806 TRANS_FLAGS(ALTIVEC, VSLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shlv);
    807 TRANS_FLAGS2(ALTIVEC_207, VSLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shlv);
    808 
    809 TRANS_FLAGS(ALTIVEC, VSRB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shrv);
    810 TRANS_FLAGS(ALTIVEC, VSRH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shrv);
    811 TRANS_FLAGS(ALTIVEC, VSRW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shrv);
    812 TRANS_FLAGS2(ALTIVEC_207, VSRD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shrv);
    813 
    814 TRANS_FLAGS(ALTIVEC, VSRAB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_sarv);
    815 TRANS_FLAGS(ALTIVEC, VSRAH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_sarv);
    816 TRANS_FLAGS(ALTIVEC, VSRAW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_sarv);
    817 TRANS_FLAGS2(ALTIVEC_207, VSRAD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_sarv);
    818 
    819 TRANS_FLAGS(ALTIVEC, VRLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_rotlv)
    820 TRANS_FLAGS(ALTIVEC, VRLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_rotlv)
    821 TRANS_FLAGS(ALTIVEC, VRLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_rotlv)
    822 TRANS_FLAGS2(ALTIVEC_207, VRLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_rotlv)
    823 
    824 static TCGv_vec do_vrl_mask_vec(unsigned vece, TCGv_vec vrb)
    825 {
    826     TCGv_vec t0 = tcg_temp_new_vec_matching(vrb),
    827              t1 = tcg_temp_new_vec_matching(vrb),
    828              t2 = tcg_temp_new_vec_matching(vrb),
    829              ones = tcg_constant_vec_matching(vrb, vece, -1);
    830 
    831     /* Extract b and e */
    832     tcg_gen_dupi_vec(vece, t2, (8 << vece) - 1);
    833 
    834     tcg_gen_shri_vec(vece, t0, vrb, 16);
    835     tcg_gen_and_vec(vece, t0, t0, t2);
    836 
    837     tcg_gen_shri_vec(vece, t1, vrb, 8);
    838     tcg_gen_and_vec(vece, t1, t1, t2);
    839 
    840     /* Compare b and e to negate the mask where begin > end */
    841     tcg_gen_cmp_vec(TCG_COND_GT, vece, t2, t0, t1);
    842 
    843     /* Create the mask with (~0 >> b) ^ ((~0 >> e) >> 1) */
    844     tcg_gen_shrv_vec(vece, t0, ones, t0);
    845     tcg_gen_shrv_vec(vece, t1, ones, t1);
    846     tcg_gen_shri_vec(vece, t1, t1, 1);
    847     tcg_gen_xor_vec(vece, t0, t0, t1);
    848 
    849     /* negate the mask */
    850     tcg_gen_xor_vec(vece, t0, t0, t2);
    851 
    852     tcg_temp_free_vec(t1);
    853     tcg_temp_free_vec(t2);
    854 
    855     return t0;
    856 }
    857 
    858 static void gen_vrlnm_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
    859                           TCGv_vec vrb)
    860 {
    861     TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt);
    862 
    863     /* Create the mask */
    864     mask = do_vrl_mask_vec(vece, vrb);
    865 
    866     /* Extract n */
    867     tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
    868     tcg_gen_and_vec(vece, n, vrb, n);
    869 
    870     /* Rotate and mask */
    871     tcg_gen_rotlv_vec(vece, vrt, vra, n);
    872     tcg_gen_and_vec(vece, vrt, vrt, mask);
    873 
    874     tcg_temp_free_vec(n);
    875     tcg_temp_free_vec(mask);
    876 }
    877 
    878 static bool do_vrlnm(DisasContext *ctx, arg_VX *a, int vece)
    879 {
    880     static const TCGOpcode vecop_list[] = {
    881         INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
    882         INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
    883     };
    884     static const GVecGen3 ops[2] = {
    885         {
    886             .fniv = gen_vrlnm_vec,
    887             .fno = gen_helper_VRLWNM,
    888             .opt_opc = vecop_list,
    889             .load_dest = true,
    890             .vece = MO_32
    891         },
    892         {
    893             .fniv = gen_vrlnm_vec,
    894             .fno = gen_helper_VRLDNM,
    895             .opt_opc = vecop_list,
    896             .load_dest = true,
    897             .vece = MO_64
    898         }
    899     };
    900 
    901     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    902     REQUIRE_VSX(ctx);
    903 
    904     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
    905                    avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
    906 
    907     return true;
    908 }
    909 
    910 TRANS(VRLWNM, do_vrlnm, MO_32)
    911 TRANS(VRLDNM, do_vrlnm, MO_64)
    912 
    913 static void gen_vrlmi_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
    914                           TCGv_vec vrb)
    915 {
    916     TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt),
    917              tmp = tcg_temp_new_vec_matching(vrt);
    918 
    919     /* Create the mask */
    920     mask = do_vrl_mask_vec(vece, vrb);
    921 
    922     /* Extract n */
    923     tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
    924     tcg_gen_and_vec(vece, n, vrb, n);
    925 
    926     /* Rotate and insert */
    927     tcg_gen_rotlv_vec(vece, tmp, vra, n);
    928     tcg_gen_bitsel_vec(vece, vrt, mask, tmp, vrt);
    929 
    930     tcg_temp_free_vec(n);
    931     tcg_temp_free_vec(tmp);
    932     tcg_temp_free_vec(mask);
    933 }
    934 
    935 static bool do_vrlmi(DisasContext *ctx, arg_VX *a, int vece)
    936 {
    937     static const TCGOpcode vecop_list[] = {
    938         INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
    939         INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
    940     };
    941     static const GVecGen3 ops[2] = {
    942         {
    943             .fniv = gen_vrlmi_vec,
    944             .fno = gen_helper_VRLWMI,
    945             .opt_opc = vecop_list,
    946             .load_dest = true,
    947             .vece = MO_32
    948         },
    949         {
    950             .fniv = gen_vrlnm_vec,
    951             .fno = gen_helper_VRLDMI,
    952             .opt_opc = vecop_list,
    953             .load_dest = true,
    954             .vece = MO_64
    955         }
    956     };
    957 
    958     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    959     REQUIRE_VSX(ctx);
    960 
    961     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
    962                    avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
    963 
    964     return true;
    965 }
    966 
    967 TRANS(VRLWMI, do_vrlmi, MO_32)
    968 TRANS(VRLDMI, do_vrlmi, MO_64)
    969 
    970 static bool do_vector_shift_quad(DisasContext *ctx, arg_VX *a, bool right,
    971                                  bool alg)
    972 {
    973     TCGv_i64 hi, lo, t0, t1, n, zero = tcg_constant_i64(0);
    974 
    975     REQUIRE_VECTOR(ctx);
    976 
    977     n = tcg_temp_new_i64();
    978     hi = tcg_temp_new_i64();
    979     lo = tcg_temp_new_i64();
    980     t0 = tcg_temp_new_i64();
    981     t1 = tcg_const_i64(0);
    982 
    983     get_avr64(lo, a->vra, false);
    984     get_avr64(hi, a->vra, true);
    985 
    986     get_avr64(n, a->vrb, true);
    987 
    988     tcg_gen_andi_i64(t0, n, 64);
    989     if (right) {
    990         tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, hi, lo);
    991         if (alg) {
    992             tcg_gen_sari_i64(t1, lo, 63);
    993         }
    994         tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, t1, hi);
    995     } else {
    996         tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, lo, hi);
    997         tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, zero, lo);
    998     }
    999     tcg_gen_andi_i64(n, n, 0x3F);
   1000 
   1001     if (right) {
   1002         if (alg) {
   1003             tcg_gen_sar_i64(t0, hi, n);
   1004         } else {
   1005             tcg_gen_shr_i64(t0, hi, n);
   1006         }
   1007     } else {
   1008         tcg_gen_shl_i64(t0, lo, n);
   1009     }
   1010     set_avr64(a->vrt, t0, right);
   1011 
   1012     if (right) {
   1013         tcg_gen_shr_i64(lo, lo, n);
   1014     } else {
   1015         tcg_gen_shl_i64(hi, hi, n);
   1016     }
   1017     tcg_gen_xori_i64(n, n, 63);
   1018     if (right) {
   1019         tcg_gen_shl_i64(hi, hi, n);
   1020         tcg_gen_shli_i64(hi, hi, 1);
   1021     } else {
   1022         tcg_gen_shr_i64(lo, lo, n);
   1023         tcg_gen_shri_i64(lo, lo, 1);
   1024     }
   1025     tcg_gen_or_i64(hi, hi, lo);
   1026     set_avr64(a->vrt, hi, !right);
   1027 
   1028     tcg_temp_free_i64(hi);
   1029     tcg_temp_free_i64(lo);
   1030     tcg_temp_free_i64(t0);
   1031     tcg_temp_free_i64(t1);
   1032     tcg_temp_free_i64(n);
   1033 
   1034     return true;
   1035 }
   1036 
   1037 TRANS_FLAGS2(ISA310, VSLQ, do_vector_shift_quad, false, false);
   1038 TRANS_FLAGS2(ISA310, VSRQ, do_vector_shift_quad, true, false);
   1039 TRANS_FLAGS2(ISA310, VSRAQ, do_vector_shift_quad, true, true);
   1040 
   1041 static void do_vrlq_mask(TCGv_i64 mh, TCGv_i64 ml, TCGv_i64 b, TCGv_i64 e)
   1042 {
   1043     TCGv_i64 th, tl, t0, t1, zero = tcg_constant_i64(0),
   1044              ones = tcg_constant_i64(-1);
   1045 
   1046     th = tcg_temp_new_i64();
   1047     tl = tcg_temp_new_i64();
   1048     t0 = tcg_temp_new_i64();
   1049     t1 = tcg_temp_new_i64();
   1050 
   1051     /* m = ~0 >> b */
   1052     tcg_gen_andi_i64(t0, b, 64);
   1053     tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
   1054     tcg_gen_andi_i64(t0, b, 0x3F);
   1055     tcg_gen_shr_i64(mh, t1, t0);
   1056     tcg_gen_shr_i64(ml, ones, t0);
   1057     tcg_gen_xori_i64(t0, t0, 63);
   1058     tcg_gen_shl_i64(t1, t1, t0);
   1059     tcg_gen_shli_i64(t1, t1, 1);
   1060     tcg_gen_or_i64(ml, t1, ml);
   1061 
   1062     /* t = ~0 >> e */
   1063     tcg_gen_andi_i64(t0, e, 64);
   1064     tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
   1065     tcg_gen_andi_i64(t0, e, 0x3F);
   1066     tcg_gen_shr_i64(th, t1, t0);
   1067     tcg_gen_shr_i64(tl, ones, t0);
   1068     tcg_gen_xori_i64(t0, t0, 63);
   1069     tcg_gen_shl_i64(t1, t1, t0);
   1070     tcg_gen_shli_i64(t1, t1, 1);
   1071     tcg_gen_or_i64(tl, t1, tl);
   1072 
   1073     /* t = t >> 1 */
   1074     tcg_gen_extract2_i64(tl, tl, th, 1);
   1075     tcg_gen_shri_i64(th, th, 1);
   1076 
   1077     /* m = m ^ t */
   1078     tcg_gen_xor_i64(mh, mh, th);
   1079     tcg_gen_xor_i64(ml, ml, tl);
   1080 
   1081     /* Negate the mask if begin > end */
   1082     tcg_gen_movcond_i64(TCG_COND_GT, t0, b, e, ones, zero);
   1083 
   1084     tcg_gen_xor_i64(mh, mh, t0);
   1085     tcg_gen_xor_i64(ml, ml, t0);
   1086 
   1087     tcg_temp_free_i64(th);
   1088     tcg_temp_free_i64(tl);
   1089     tcg_temp_free_i64(t0);
   1090     tcg_temp_free_i64(t1);
   1091 }
   1092 
   1093 static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask,
   1094                                 bool insert)
   1095 {
   1096     TCGv_i64 ah, al, vrb, n, t0, t1, zero = tcg_constant_i64(0);
   1097 
   1098     REQUIRE_VECTOR(ctx);
   1099     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1100 
   1101     ah = tcg_temp_new_i64();
   1102     al = tcg_temp_new_i64();
   1103     vrb = tcg_temp_new_i64();
   1104     n = tcg_temp_new_i64();
   1105     t0 = tcg_temp_new_i64();
   1106     t1 = tcg_temp_new_i64();
   1107 
   1108     get_avr64(ah, a->vra, true);
   1109     get_avr64(al, a->vra, false);
   1110     get_avr64(vrb, a->vrb, true);
   1111 
   1112     tcg_gen_mov_i64(t0, ah);
   1113     tcg_gen_andi_i64(t1, vrb, 64);
   1114     tcg_gen_movcond_i64(TCG_COND_NE, ah, t1, zero, al, ah);
   1115     tcg_gen_movcond_i64(TCG_COND_NE, al, t1, zero, t0, al);
   1116     tcg_gen_andi_i64(n, vrb, 0x3F);
   1117 
   1118     tcg_gen_shl_i64(t0, ah, n);
   1119     tcg_gen_shl_i64(t1, al, n);
   1120 
   1121     tcg_gen_xori_i64(n, n, 63);
   1122 
   1123     tcg_gen_shr_i64(al, al, n);
   1124     tcg_gen_shri_i64(al, al, 1);
   1125     tcg_gen_or_i64(t0, al, t0);
   1126 
   1127     tcg_gen_shr_i64(ah, ah, n);
   1128     tcg_gen_shri_i64(ah, ah, 1);
   1129     tcg_gen_or_i64(t1, ah, t1);
   1130 
   1131     if (mask || insert) {
   1132         tcg_gen_extract_i64(n, vrb, 8, 7);
   1133         tcg_gen_extract_i64(vrb, vrb, 16, 7);
   1134 
   1135         do_vrlq_mask(ah, al, vrb, n);
   1136 
   1137         tcg_gen_and_i64(t0, t0, ah);
   1138         tcg_gen_and_i64(t1, t1, al);
   1139 
   1140         if (insert) {
   1141             get_avr64(n, a->vrt, true);
   1142             get_avr64(vrb, a->vrt, false);
   1143             tcg_gen_andc_i64(n, n, ah);
   1144             tcg_gen_andc_i64(vrb, vrb, al);
   1145             tcg_gen_or_i64(t0, t0, n);
   1146             tcg_gen_or_i64(t1, t1, vrb);
   1147         }
   1148     }
   1149 
   1150     set_avr64(a->vrt, t0, true);
   1151     set_avr64(a->vrt, t1, false);
   1152 
   1153     tcg_temp_free_i64(ah);
   1154     tcg_temp_free_i64(al);
   1155     tcg_temp_free_i64(vrb);
   1156     tcg_temp_free_i64(n);
   1157     tcg_temp_free_i64(t0);
   1158     tcg_temp_free_i64(t1);
   1159 
   1160     return true;
   1161 }
   1162 
   1163 TRANS(VRLQ, do_vector_rotl_quad, false, false)
   1164 TRANS(VRLQNM, do_vector_rotl_quad, true, false)
   1165 TRANS(VRLQMI, do_vector_rotl_quad, false, true)
   1166 
   1167 #define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3)               \
   1168 static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t,     \
   1169                                          TCGv_vec sat, TCGv_vec a,      \
   1170                                          TCGv_vec b)                    \
   1171 {                                                                       \
   1172     TCGv_vec x = tcg_temp_new_vec_matching(t);                          \
   1173     glue(glue(tcg_gen_, NORM), _vec)(VECE, x, a, b);                    \
   1174     glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b);                     \
   1175     tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t);                        \
   1176     tcg_gen_or_vec(VECE, sat, sat, x);                                  \
   1177     tcg_temp_free_vec(x);                                               \
   1178 }                                                                       \
   1179 static void glue(gen_, NAME)(DisasContext *ctx)                         \
   1180 {                                                                       \
   1181     static const TCGOpcode vecop_list[] = {                             \
   1182         glue(glue(INDEX_op_, NORM), _vec),                              \
   1183         glue(glue(INDEX_op_, SAT), _vec),                               \
   1184         INDEX_op_cmp_vec, 0                                             \
   1185     };                                                                  \
   1186     static const GVecGen4 g = {                                         \
   1187         .fniv = glue(glue(gen_, NAME), _vec),                           \
   1188         .fno = glue(gen_helper_, NAME),                                 \
   1189         .opt_opc = vecop_list,                                          \
   1190         .write_aofs = true,                                             \
   1191         .vece = VECE,                                                   \
   1192     };                                                                  \
   1193     if (unlikely(!ctx->altivec_enabled)) {                              \
   1194         gen_exception(ctx, POWERPC_EXCP_VPU);                           \
   1195         return;                                                         \
   1196     }                                                                   \
   1197     tcg_gen_gvec_4(avr_full_offset(rD(ctx->opcode)),                    \
   1198                    offsetof(CPUPPCState, vscr_sat),                     \
   1199                    avr_full_offset(rA(ctx->opcode)),                    \
   1200                    avr_full_offset(rB(ctx->opcode)),                    \
   1201                    16, 16, &g);                                         \
   1202 }
   1203 
   1204 GEN_VXFORM_SAT(vaddubs, MO_8, add, usadd, 0, 8);
   1205 GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0,       \
   1206                     vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
   1207 GEN_VXFORM_SAT(vadduhs, MO_16, add, usadd, 0, 9);
   1208 GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
   1209                 vmul10euq, PPC_NONE, PPC2_ISA300)
   1210 GEN_VXFORM_SAT(vadduws, MO_32, add, usadd, 0, 10);
   1211 GEN_VXFORM_SAT(vaddsbs, MO_8, add, ssadd, 0, 12);
   1212 GEN_VXFORM_SAT(vaddshs, MO_16, add, ssadd, 0, 13);
   1213 GEN_VXFORM_SAT(vaddsws, MO_32, add, ssadd, 0, 14);
   1214 GEN_VXFORM_SAT(vsububs, MO_8, sub, ussub, 0, 24);
   1215 GEN_VXFORM_SAT(vsubuhs, MO_16, sub, ussub, 0, 25);
   1216 GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
   1217 GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
   1218 GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
   1219 GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
   1220 GEN_VXFORM_TRANS(vsl, 2, 7);
   1221 GEN_VXFORM_TRANS(vsr, 2, 11);
   1222 GEN_VXFORM_ENV(vpkuhum, 7, 0);
   1223 GEN_VXFORM_ENV(vpkuwum, 7, 1);
   1224 GEN_VXFORM_ENV(vpkudum, 7, 17);
   1225 GEN_VXFORM_ENV(vpkuhus, 7, 2);
   1226 GEN_VXFORM_ENV(vpkuwus, 7, 3);
   1227 GEN_VXFORM_ENV(vpkudus, 7, 19);
   1228 GEN_VXFORM_ENV(vpkshus, 7, 4);
   1229 GEN_VXFORM_ENV(vpkswus, 7, 5);
   1230 GEN_VXFORM_ENV(vpksdus, 7, 21);
   1231 GEN_VXFORM_ENV(vpkshss, 7, 6);
   1232 GEN_VXFORM_ENV(vpkswss, 7, 7);
   1233 GEN_VXFORM_ENV(vpksdss, 7, 23);
   1234 GEN_VXFORM(vpkpx, 7, 12);
   1235 GEN_VXFORM_ENV(vsum4ubs, 4, 24);
   1236 GEN_VXFORM_ENV(vsum4sbs, 4, 28);
   1237 GEN_VXFORM_ENV(vsum4shs, 4, 25);
   1238 GEN_VXFORM_ENV(vsum2sws, 4, 26);
   1239 GEN_VXFORM_ENV(vsumsws, 4, 30);
   1240 GEN_VXFORM_ENV(vaddfp, 5, 0);
   1241 GEN_VXFORM_ENV(vsubfp, 5, 1);
   1242 GEN_VXFORM_ENV(vmaxfp, 5, 16);
   1243 GEN_VXFORM_ENV(vminfp, 5, 17);
   1244 GEN_VXFORM_HETRO(vextublx, 6, 24)
   1245 GEN_VXFORM_HETRO(vextuhlx, 6, 25)
   1246 GEN_VXFORM_HETRO(vextuwlx, 6, 26)
   1247 GEN_VXFORM_TRANS_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207,
   1248                 vextuwlx, PPC_NONE, PPC2_ISA300)
   1249 GEN_VXFORM_HETRO(vextubrx, 6, 28)
   1250 GEN_VXFORM_HETRO(vextuhrx, 6, 29)
   1251 GEN_VXFORM_HETRO(vextuwrx, 6, 30)
   1252 GEN_VXFORM_TRANS(lvsl, 6, 31)
   1253 GEN_VXFORM_TRANS(lvsr, 6, 32)
   1254 GEN_VXFORM_TRANS_DUAL(vmrgew, PPC_NONE, PPC2_ALTIVEC_207,
   1255                 vextuwrx, PPC_NONE, PPC2_ISA300)
   1256 
   1257 #define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
   1258 static void glue(gen_, name)(DisasContext *ctx)                         \
   1259     {                                                                   \
   1260         TCGv_ptr ra, rb, rd;                                            \
   1261         if (unlikely(!ctx->altivec_enabled)) {                          \
   1262             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1263             return;                                                     \
   1264         }                                                               \
   1265         ra = gen_avr_ptr(rA(ctx->opcode));                              \
   1266         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1267         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1268         gen_helper_##opname(cpu_env, rd, ra, rb);                       \
   1269         tcg_temp_free_ptr(ra);                                          \
   1270         tcg_temp_free_ptr(rb);                                          \
   1271         tcg_temp_free_ptr(rd);                                          \
   1272     }
   1273 
   1274 #define GEN_VXRFORM(name, opc2, opc3)                                \
   1275     GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
   1276     GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
   1277 
   1278 /*
   1279  * Support for Altivec instructions that use bit 31 (Rc) as an opcode
   1280  * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
   1281  * come from different versions of the ISA, so we must also support a
   1282  * pair of flags for each instruction.
   1283  */
   1284 #define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
   1285 static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
   1286 {                                                                      \
   1287     if ((Rc(ctx->opcode) == 0) &&                                      \
   1288         ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
   1289         if (Rc21(ctx->opcode) == 0) {                                  \
   1290             gen_##name0(ctx);                                          \
   1291         } else {                                                       \
   1292             gen_##name0##_(ctx);                                       \
   1293         }                                                              \
   1294     } else if ((Rc(ctx->opcode) == 1) &&                               \
   1295         ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
   1296         if (Rc21(ctx->opcode) == 0) {                                  \
   1297             gen_##name1(ctx);                                          \
   1298         } else {                                                       \
   1299             gen_##name1##_(ctx);                                       \
   1300         }                                                              \
   1301     } else {                                                           \
   1302         gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
   1303     }                                                                  \
   1304 }
   1305 
   1306 static void do_vcmp_rc(int vrt)
   1307 {
   1308     TCGv_i64 tmp, set, clr;
   1309 
   1310     tmp = tcg_temp_new_i64();
   1311     set = tcg_temp_new_i64();
   1312     clr = tcg_temp_new_i64();
   1313 
   1314     get_avr64(tmp, vrt, true);
   1315     tcg_gen_mov_i64(set, tmp);
   1316     get_avr64(tmp, vrt, false);
   1317     tcg_gen_or_i64(clr, set, tmp);
   1318     tcg_gen_and_i64(set, set, tmp);
   1319 
   1320     tcg_gen_setcondi_i64(TCG_COND_EQ, clr, clr, 0);
   1321     tcg_gen_shli_i64(clr, clr, 1);
   1322 
   1323     tcg_gen_setcondi_i64(TCG_COND_EQ, set, set, -1);
   1324     tcg_gen_shli_i64(set, set, 3);
   1325 
   1326     tcg_gen_or_i64(tmp, set, clr);
   1327     tcg_gen_extrl_i64_i32(cpu_crf[6], tmp);
   1328 
   1329     tcg_temp_free_i64(tmp);
   1330     tcg_temp_free_i64(set);
   1331     tcg_temp_free_i64(clr);
   1332 }
   1333 
   1334 static bool do_vcmp(DisasContext *ctx, arg_VC *a, TCGCond cond, int vece)
   1335 {
   1336     REQUIRE_VECTOR(ctx);
   1337 
   1338     tcg_gen_gvec_cmp(cond, vece, avr_full_offset(a->vrt),
   1339                      avr_full_offset(a->vra), avr_full_offset(a->vrb), 16, 16);
   1340 
   1341     if (a->rc) {
   1342         do_vcmp_rc(a->vrt);
   1343     }
   1344 
   1345     return true;
   1346 }
   1347 
   1348 TRANS_FLAGS(ALTIVEC, VCMPEQUB, do_vcmp, TCG_COND_EQ, MO_8)
   1349 TRANS_FLAGS(ALTIVEC, VCMPEQUH, do_vcmp, TCG_COND_EQ, MO_16)
   1350 TRANS_FLAGS(ALTIVEC, VCMPEQUW, do_vcmp, TCG_COND_EQ, MO_32)
   1351 TRANS_FLAGS2(ALTIVEC_207, VCMPEQUD, do_vcmp, TCG_COND_EQ, MO_64)
   1352 
   1353 TRANS_FLAGS(ALTIVEC, VCMPGTSB, do_vcmp, TCG_COND_GT, MO_8)
   1354 TRANS_FLAGS(ALTIVEC, VCMPGTSH, do_vcmp, TCG_COND_GT, MO_16)
   1355 TRANS_FLAGS(ALTIVEC, VCMPGTSW, do_vcmp, TCG_COND_GT, MO_32)
   1356 TRANS_FLAGS2(ALTIVEC_207, VCMPGTSD, do_vcmp, TCG_COND_GT, MO_64)
   1357 TRANS_FLAGS(ALTIVEC, VCMPGTUB, do_vcmp, TCG_COND_GTU, MO_8)
   1358 TRANS_FLAGS(ALTIVEC, VCMPGTUH, do_vcmp, TCG_COND_GTU, MO_16)
   1359 TRANS_FLAGS(ALTIVEC, VCMPGTUW, do_vcmp, TCG_COND_GTU, MO_32)
   1360 TRANS_FLAGS2(ALTIVEC_207, VCMPGTUD, do_vcmp, TCG_COND_GTU, MO_64)
   1361 
   1362 TRANS_FLAGS2(ISA300, VCMPNEB, do_vcmp, TCG_COND_NE, MO_8)
   1363 TRANS_FLAGS2(ISA300, VCMPNEH, do_vcmp, TCG_COND_NE, MO_16)
   1364 TRANS_FLAGS2(ISA300, VCMPNEW, do_vcmp, TCG_COND_NE, MO_32)
   1365 
   1366 static void gen_vcmpnez_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   1367 {
   1368     TCGv_vec t0, t1, zero;
   1369 
   1370     t0 = tcg_temp_new_vec_matching(t);
   1371     t1 = tcg_temp_new_vec_matching(t);
   1372     zero = tcg_constant_vec_matching(t, vece, 0);
   1373 
   1374     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t0, a, zero);
   1375     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t1, b, zero);
   1376     tcg_gen_cmp_vec(TCG_COND_NE, vece, t, a, b);
   1377 
   1378     tcg_gen_or_vec(vece, t, t, t0);
   1379     tcg_gen_or_vec(vece, t, t, t1);
   1380 
   1381     tcg_temp_free_vec(t0);
   1382     tcg_temp_free_vec(t1);
   1383 }
   1384 
   1385 static bool do_vcmpnez(DisasContext *ctx, arg_VC *a, int vece)
   1386 {
   1387     static const TCGOpcode vecop_list[] = {
   1388         INDEX_op_cmp_vec, 0
   1389     };
   1390     static const GVecGen3 ops[3] = {
   1391         {
   1392             .fniv = gen_vcmpnez_vec,
   1393             .fno = gen_helper_VCMPNEZB,
   1394             .opt_opc = vecop_list,
   1395             .vece = MO_8
   1396         },
   1397         {
   1398             .fniv = gen_vcmpnez_vec,
   1399             .fno = gen_helper_VCMPNEZH,
   1400             .opt_opc = vecop_list,
   1401             .vece = MO_16
   1402         },
   1403         {
   1404             .fniv = gen_vcmpnez_vec,
   1405             .fno = gen_helper_VCMPNEZW,
   1406             .opt_opc = vecop_list,
   1407             .vece = MO_32
   1408         }
   1409     };
   1410 
   1411     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   1412     REQUIRE_VECTOR(ctx);
   1413 
   1414     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   1415                    avr_full_offset(a->vrb), 16, 16, &ops[vece]);
   1416 
   1417     if (a->rc) {
   1418         do_vcmp_rc(a->vrt);
   1419     }
   1420 
   1421     return true;
   1422 }
   1423 
   1424 TRANS(VCMPNEZB, do_vcmpnez, MO_8)
   1425 TRANS(VCMPNEZH, do_vcmpnez, MO_16)
   1426 TRANS(VCMPNEZW, do_vcmpnez, MO_32)
   1427 
   1428 static bool trans_VCMPEQUQ(DisasContext *ctx, arg_VC *a)
   1429 {
   1430     TCGv_i64 t0, t1, t2;
   1431 
   1432     t0 = tcg_temp_new_i64();
   1433     t1 = tcg_temp_new_i64();
   1434     t2 = tcg_temp_new_i64();
   1435 
   1436     get_avr64(t0, a->vra, true);
   1437     get_avr64(t1, a->vrb, true);
   1438     tcg_gen_xor_i64(t2, t0, t1);
   1439 
   1440     get_avr64(t0, a->vra, false);
   1441     get_avr64(t1, a->vrb, false);
   1442     tcg_gen_xor_i64(t1, t0, t1);
   1443 
   1444     tcg_gen_or_i64(t1, t1, t2);
   1445     tcg_gen_setcondi_i64(TCG_COND_EQ, t1, t1, 0);
   1446     tcg_gen_neg_i64(t1, t1);
   1447 
   1448     set_avr64(a->vrt, t1, true);
   1449     set_avr64(a->vrt, t1, false);
   1450 
   1451     if (a->rc) {
   1452         tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
   1453         tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
   1454         tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
   1455     }
   1456 
   1457     tcg_temp_free_i64(t0);
   1458     tcg_temp_free_i64(t1);
   1459     tcg_temp_free_i64(t2);
   1460 
   1461     return true;
   1462 }
   1463 
   1464 static bool do_vcmpgtq(DisasContext *ctx, arg_VC *a, bool sign)
   1465 {
   1466     TCGv_i64 t0, t1, t2;
   1467 
   1468     t0 = tcg_temp_new_i64();
   1469     t1 = tcg_temp_new_i64();
   1470     t2 = tcg_temp_new_i64();
   1471 
   1472     get_avr64(t0, a->vra, false);
   1473     get_avr64(t1, a->vrb, false);
   1474     tcg_gen_setcond_i64(TCG_COND_GTU, t2, t0, t1);
   1475 
   1476     get_avr64(t0, a->vra, true);
   1477     get_avr64(t1, a->vrb, true);
   1478     tcg_gen_movcond_i64(TCG_COND_EQ, t2, t0, t1, t2, tcg_constant_i64(0));
   1479     tcg_gen_setcond_i64(sign ? TCG_COND_GT : TCG_COND_GTU, t1, t0, t1);
   1480 
   1481     tcg_gen_or_i64(t1, t1, t2);
   1482     tcg_gen_neg_i64(t1, t1);
   1483 
   1484     set_avr64(a->vrt, t1, true);
   1485     set_avr64(a->vrt, t1, false);
   1486 
   1487     if (a->rc) {
   1488         tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
   1489         tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
   1490         tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
   1491     }
   1492 
   1493     tcg_temp_free_i64(t0);
   1494     tcg_temp_free_i64(t1);
   1495     tcg_temp_free_i64(t2);
   1496 
   1497     return true;
   1498 }
   1499 
   1500 TRANS(VCMPGTSQ, do_vcmpgtq, true)
   1501 TRANS(VCMPGTUQ, do_vcmpgtq, false)
   1502 
   1503 static bool do_vcmpq(DisasContext *ctx, arg_VX_bf *a, bool sign)
   1504 {
   1505     TCGv_i64 vra, vrb;
   1506     TCGLabel *gt, *lt, *done;
   1507 
   1508     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1509     REQUIRE_VECTOR(ctx);
   1510 
   1511     vra = tcg_temp_local_new_i64();
   1512     vrb = tcg_temp_local_new_i64();
   1513     gt = gen_new_label();
   1514     lt = gen_new_label();
   1515     done = gen_new_label();
   1516 
   1517     get_avr64(vra, a->vra, true);
   1518     get_avr64(vrb, a->vrb, true);
   1519     tcg_gen_brcond_i64((sign ? TCG_COND_GT : TCG_COND_GTU), vra, vrb, gt);
   1520     tcg_gen_brcond_i64((sign ? TCG_COND_LT : TCG_COND_LTU), vra, vrb, lt);
   1521 
   1522     get_avr64(vra, a->vra, false);
   1523     get_avr64(vrb, a->vrb, false);
   1524     tcg_gen_brcond_i64(TCG_COND_GTU, vra, vrb, gt);
   1525     tcg_gen_brcond_i64(TCG_COND_LTU, vra, vrb, lt);
   1526 
   1527     tcg_gen_movi_i32(cpu_crf[a->bf], CRF_EQ);
   1528     tcg_gen_br(done);
   1529 
   1530     gen_set_label(gt);
   1531     tcg_gen_movi_i32(cpu_crf[a->bf], CRF_GT);
   1532     tcg_gen_br(done);
   1533 
   1534     gen_set_label(lt);
   1535     tcg_gen_movi_i32(cpu_crf[a->bf], CRF_LT);
   1536     tcg_gen_br(done);
   1537 
   1538     gen_set_label(done);
   1539     tcg_temp_free_i64(vra);
   1540     tcg_temp_free_i64(vrb);
   1541 
   1542     return true;
   1543 }
   1544 
   1545 TRANS(VCMPSQ, do_vcmpq, true)
   1546 TRANS(VCMPUQ, do_vcmpq, false)
   1547 
   1548 GEN_VXRFORM(vcmpeqfp, 3, 3)
   1549 GEN_VXRFORM(vcmpgefp, 3, 7)
   1550 GEN_VXRFORM(vcmpgtfp, 3, 11)
   1551 GEN_VXRFORM(vcmpbfp, 3, 15)
   1552 
   1553 static void gen_vsplti(DisasContext *ctx, int vece)
   1554 {
   1555     int simm;
   1556 
   1557     if (unlikely(!ctx->altivec_enabled)) {
   1558         gen_exception(ctx, POWERPC_EXCP_VPU);
   1559         return;
   1560     }
   1561 
   1562     simm = SIMM5(ctx->opcode);
   1563     tcg_gen_gvec_dup_imm(vece, avr_full_offset(rD(ctx->opcode)), 16, 16, simm);
   1564 }
   1565 
   1566 #define GEN_VXFORM_VSPLTI(name, vece, opc2, opc3) \
   1567 static void glue(gen_, name)(DisasContext *ctx) { gen_vsplti(ctx, vece); }
   1568 
   1569 GEN_VXFORM_VSPLTI(vspltisb, MO_8, 6, 12);
   1570 GEN_VXFORM_VSPLTI(vspltish, MO_16, 6, 13);
   1571 GEN_VXFORM_VSPLTI(vspltisw, MO_32, 6, 14);
   1572 
   1573 #define GEN_VXFORM_NOA(name, opc2, opc3)                                \
   1574 static void glue(gen_, name)(DisasContext *ctx)                         \
   1575     {                                                                   \
   1576         TCGv_ptr rb, rd;                                                \
   1577         if (unlikely(!ctx->altivec_enabled)) {                          \
   1578             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1579             return;                                                     \
   1580         }                                                               \
   1581         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1582         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1583         gen_helper_##name(rd, rb);                                      \
   1584         tcg_temp_free_ptr(rb);                                          \
   1585         tcg_temp_free_ptr(rd);                                          \
   1586     }
   1587 
   1588 #define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
   1589 static void glue(gen_, name)(DisasContext *ctx)                         \
   1590     {                                                                   \
   1591         TCGv_ptr rb, rd;                                                \
   1592                                                                         \
   1593         if (unlikely(!ctx->altivec_enabled)) {                          \
   1594             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1595             return;                                                     \
   1596         }                                                               \
   1597         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1598         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1599         gen_helper_##name(cpu_env, rd, rb);                             \
   1600         tcg_temp_free_ptr(rb);                                          \
   1601         tcg_temp_free_ptr(rd);                                          \
   1602     }
   1603 
   1604 #define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4)                        \
   1605 static void glue(gen_, name)(DisasContext *ctx)                         \
   1606     {                                                                   \
   1607         TCGv_ptr rb, rd;                                                \
   1608         if (unlikely(!ctx->altivec_enabled)) {                          \
   1609             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1610             return;                                                     \
   1611         }                                                               \
   1612         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1613         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1614         gen_helper_##name(rd, rb);                                      \
   1615         tcg_temp_free_ptr(rb);                                          \
   1616         tcg_temp_free_ptr(rd);                                          \
   1617     }
   1618 
   1619 #define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4)                        \
   1620 static void glue(gen_, name)(DisasContext *ctx)                         \
   1621     {                                                                   \
   1622         TCGv_ptr rb;                                                    \
   1623         if (unlikely(!ctx->altivec_enabled)) {                          \
   1624             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1625             return;                                                     \
   1626         }                                                               \
   1627         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1628         gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb);                \
   1629         tcg_temp_free_ptr(rb);                                          \
   1630     }
   1631 GEN_VXFORM_NOA(vupkhsb, 7, 8);
   1632 GEN_VXFORM_NOA(vupkhsh, 7, 9);
   1633 GEN_VXFORM_NOA(vupkhsw, 7, 25);
   1634 GEN_VXFORM_NOA(vupklsb, 7, 10);
   1635 GEN_VXFORM_NOA(vupklsh, 7, 11);
   1636 GEN_VXFORM_NOA(vupklsw, 7, 27);
   1637 GEN_VXFORM_NOA(vupkhpx, 7, 13);
   1638 GEN_VXFORM_NOA(vupklpx, 7, 15);
   1639 GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
   1640 GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
   1641 GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
   1642 GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
   1643 GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
   1644 GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
   1645 GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
   1646 GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
   1647 
   1648 static void gen_vprtyb_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
   1649 {
   1650     int i;
   1651     TCGv_vec tmp = tcg_temp_new_vec_matching(b);
   1652     /* MO_32 is 2, so 2 iteractions for MO_32 and 3 for MO_64 */
   1653     for (i = 0; i < vece; i++) {
   1654         tcg_gen_shri_vec(vece, tmp, b, (4 << (vece - i)));
   1655         tcg_gen_xor_vec(vece, b, tmp, b);
   1656     }
   1657     tcg_gen_and_vec(vece, t, b, tcg_constant_vec_matching(t, vece, 1));
   1658     tcg_temp_free_vec(tmp);
   1659 }
   1660 
   1661 /* vprtybw */
   1662 static void gen_vprtyb_i32(TCGv_i32 t, TCGv_i32 b)
   1663 {
   1664     tcg_gen_ctpop_i32(t, b);
   1665     tcg_gen_and_i32(t, t, tcg_constant_i32(1));
   1666 }
   1667 
   1668 /* vprtybd */
   1669 static void gen_vprtyb_i64(TCGv_i64 t, TCGv_i64 b)
   1670 {
   1671     tcg_gen_ctpop_i64(t, b);
   1672     tcg_gen_and_i64(t, t, tcg_constant_i64(1));
   1673 }
   1674 
   1675 static bool do_vx_vprtyb(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
   1676 {
   1677     static const TCGOpcode vecop_list[] = {
   1678         INDEX_op_shri_vec, 0
   1679     };
   1680 
   1681     static const GVecGen2 op[] = {
   1682         {
   1683             .fniv = gen_vprtyb_vec,
   1684             .fni4 = gen_vprtyb_i32,
   1685             .opt_opc = vecop_list,
   1686             .vece = MO_32
   1687         },
   1688         {
   1689             .fniv = gen_vprtyb_vec,
   1690             .fni8 = gen_vprtyb_i64,
   1691             .opt_opc = vecop_list,
   1692             .vece = MO_64
   1693         },
   1694         {
   1695             .fno = gen_helper_VPRTYBQ,
   1696             .vece = MO_128
   1697         },
   1698     };
   1699 
   1700     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   1701     REQUIRE_VECTOR(ctx);
   1702 
   1703     tcg_gen_gvec_2(avr_full_offset(a->vrt), avr_full_offset(a->vrb),
   1704                    16, 16, &op[vece - MO_32]);
   1705 
   1706     return true;
   1707 }
   1708 
   1709 TRANS(VPRTYBW, do_vx_vprtyb, MO_32)
   1710 TRANS(VPRTYBD, do_vx_vprtyb, MO_64)
   1711 TRANS(VPRTYBQ, do_vx_vprtyb, MO_128)
   1712 
   1713 static void gen_vsplt(DisasContext *ctx, int vece)
   1714 {
   1715     int uimm, dofs, bofs;
   1716 
   1717     if (unlikely(!ctx->altivec_enabled)) {
   1718         gen_exception(ctx, POWERPC_EXCP_VPU);
   1719         return;
   1720     }
   1721 
   1722     uimm = UIMM5(ctx->opcode);
   1723     bofs = avr_full_offset(rB(ctx->opcode));
   1724     dofs = avr_full_offset(rD(ctx->opcode));
   1725 
   1726     /* Experimental testing shows that hardware masks the immediate.  */
   1727     bofs += (uimm << vece) & 15;
   1728 #if !HOST_BIG_ENDIAN
   1729     bofs ^= 15;
   1730     bofs &= ~((1 << vece) - 1);
   1731 #endif
   1732 
   1733     tcg_gen_gvec_dup_mem(vece, dofs, bofs, 16, 16);
   1734 }
   1735 
   1736 #define GEN_VXFORM_VSPLT(name, vece, opc2, opc3) \
   1737 static void glue(gen_, name)(DisasContext *ctx) { gen_vsplt(ctx, vece); }
   1738 
   1739 #define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
   1740 static void glue(gen_, name)(DisasContext *ctx)                         \
   1741     {                                                                   \
   1742         TCGv_ptr rb, rd;                                                \
   1743         TCGv_i32 uimm;                                                  \
   1744                                                                         \
   1745         if (unlikely(!ctx->altivec_enabled)) {                          \
   1746             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1747             return;                                                     \
   1748         }                                                               \
   1749         uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
   1750         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1751         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1752         gen_helper_##name(cpu_env, rd, rb, uimm);                       \
   1753         tcg_temp_free_i32(uimm);                                        \
   1754         tcg_temp_free_ptr(rb);                                          \
   1755         tcg_temp_free_ptr(rd);                                          \
   1756     }
   1757 
   1758 #define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max)              \
   1759 static void glue(gen_, name)(DisasContext *ctx)                         \
   1760     {                                                                   \
   1761         TCGv_ptr rb, rd;                                                \
   1762         uint8_t uimm = UIMM4(ctx->opcode);                              \
   1763         TCGv_i32 t0;                                                    \
   1764         if (unlikely(!ctx->altivec_enabled)) {                          \
   1765             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   1766             return;                                                     \
   1767         }                                                               \
   1768         if (uimm > splat_max) {                                         \
   1769             uimm = 0;                                                   \
   1770         }                                                               \
   1771         t0 = tcg_temp_new_i32();                                        \
   1772         tcg_gen_movi_i32(t0, uimm);                                     \
   1773         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   1774         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   1775         gen_helper_##name(rd, rb, t0);                                  \
   1776         tcg_temp_free_i32(t0);                                          \
   1777         tcg_temp_free_ptr(rb);                                          \
   1778         tcg_temp_free_ptr(rd);                                          \
   1779     }
   1780 
   1781 GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
   1782 GEN_VXFORM_VSPLT(vsplth, MO_16, 6, 9);
   1783 GEN_VXFORM_VSPLT(vspltw, MO_32, 6, 10);
   1784 GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
   1785 GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
   1786 GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
   1787 GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
   1788 GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
   1789 GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
   1790 GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
   1791 GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
   1792 GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
   1793                 vextractub, PPC_NONE, PPC2_ISA300);
   1794 GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
   1795                 vextractuh, PPC_NONE, PPC2_ISA300);
   1796 GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
   1797                 vextractuw, PPC_NONE, PPC2_ISA300);
   1798 
   1799 static bool trans_VGNB(DisasContext *ctx, arg_VX_n *a)
   1800 {
   1801     /*
   1802      * Similar to do_vextractm, we'll use a sequence of mask-shift-or operations
   1803      * to gather the bits. The masks can be created with
   1804      *
   1805      * uint64_t mask(uint64_t n, uint64_t step)
   1806      * {
   1807      *     uint64_t p = ((1UL << (1UL << step)) - 1UL) << ((n - 1UL) << step),
   1808      *                  plen = n << step, m = 0;
   1809      *     for(int i = 0; i < 64/plen; i++) {
   1810      *         m |= p;
   1811      *         m = ror64(m, plen);
   1812      *     }
   1813      *     p >>= plen * DIV_ROUND_UP(64, plen) - 64;
   1814      *     return m | p;
   1815      * }
   1816      *
   1817      * But since there are few values of N, we'll use a lookup table to avoid
   1818      * these calculations at runtime.
   1819      */
   1820     static const uint64_t mask[6][5] = {
   1821         {
   1822             0xAAAAAAAAAAAAAAAAULL, 0xccccccccccccccccULL, 0xf0f0f0f0f0f0f0f0ULL,
   1823             0xff00ff00ff00ff00ULL, 0xffff0000ffff0000ULL
   1824         },
   1825         {
   1826             0x9249249249249249ULL, 0xC30C30C30C30C30CULL, 0xF00F00F00F00F00FULL,
   1827             0xFF0000FF0000FF00ULL, 0xFFFF00000000FFFFULL
   1828         },
   1829         {
   1830             /* For N >= 4, some mask operations can be elided */
   1831             0x8888888888888888ULL, 0, 0xf000f000f000f000ULL, 0,
   1832             0xFFFF000000000000ULL
   1833         },
   1834         {
   1835             0x8421084210842108ULL, 0, 0xF0000F0000F0000FULL, 0, 0
   1836         },
   1837         {
   1838             0x8208208208208208ULL, 0, 0xF00000F00000F000ULL, 0, 0
   1839         },
   1840         {
   1841             0x8102040810204081ULL, 0, 0xF000000F000000F0ULL, 0, 0
   1842         }
   1843     };
   1844     uint64_t m;
   1845     int i, sh, nbits = DIV_ROUND_UP(64, a->n);
   1846     TCGv_i64 hi, lo, t0, t1;
   1847 
   1848     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1849     REQUIRE_VECTOR(ctx);
   1850 
   1851     if (a->n < 2) {
   1852         /*
   1853          * "N can be any value between 2 and 7, inclusive." Otherwise, the
   1854          * result is undefined, so we don't need to change RT. Also, N > 7 is
   1855          * impossible since the immediate field is 3 bits only.
   1856          */
   1857         return true;
   1858     }
   1859 
   1860     hi = tcg_temp_new_i64();
   1861     lo = tcg_temp_new_i64();
   1862     t0 = tcg_temp_new_i64();
   1863     t1 = tcg_temp_new_i64();
   1864 
   1865     get_avr64(hi, a->vrb, true);
   1866     get_avr64(lo, a->vrb, false);
   1867 
   1868     /* Align the lower doubleword so we can use the same mask */
   1869     tcg_gen_shli_i64(lo, lo, a->n * nbits - 64);
   1870 
   1871     /*
   1872      * Starting from the most significant bit, gather every Nth bit with a
   1873      * sequence of mask-shift-or operation. E.g.: for N=3
   1874      * AxxBxxCxxDxxExxFxxGxxHxxIxxJxxKxxLxxMxxNxxOxxPxxQxxRxxSxxTxxUxxV
   1875      *     & rep(0b100)
   1876      * A..B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V
   1877      *     << 2
   1878      * .B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V..
   1879      *     |
   1880      * AB.BC.CD.DE.EF.FG.GH.HI.IJ.JK.KL.LM.MN.NO.OP.PQ.QR.RS.ST.TU.UV.V
   1881      *  & rep(0b110000)
   1882      * AB....CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV..
   1883      *     << 4
   1884      * ..CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV......
   1885      *     |
   1886      * ABCD..CDEF..EFGH..GHIJ..IJKL..KLMN..MNOP..OPQR..QRST..STUV..UV..
   1887      *     & rep(0b111100000000)
   1888      * ABCD........EFGH........IJKL........MNOP........QRST........UV..
   1889      *     << 8
   1890      * ....EFGH........IJKL........MNOP........QRST........UV..........
   1891      *     |
   1892      * ABCDEFGH....EFGHIJKL....IJKLMNOP....MNOPQRST....QRSTUV......UV..
   1893      *  & rep(0b111111110000000000000000)
   1894      * ABCDEFGH................IJKLMNOP................QRSTUV..........
   1895      *     << 16
   1896      * ........IJKLMNOP................QRSTUV..........................
   1897      *     |
   1898      * ABCDEFGHIJKLMNOP........IJKLMNOPQRSTUV..........QRSTUV..........
   1899      *     & rep(0b111111111111111100000000000000000000000000000000)
   1900      * ABCDEFGHIJKLMNOP................................QRSTUV..........
   1901      *     << 32
   1902      * ................QRSTUV..........................................
   1903      *     |
   1904      * ABCDEFGHIJKLMNOPQRSTUV..........................QRSTUV..........
   1905      */
   1906     for (i = 0, sh = a->n - 1; i < 5; i++, sh <<= 1) {
   1907         m = mask[a->n - 2][i];
   1908         if (m) {
   1909             tcg_gen_andi_i64(hi, hi, m);
   1910             tcg_gen_andi_i64(lo, lo, m);
   1911         }
   1912         if (sh < 64) {
   1913             tcg_gen_shli_i64(t0, hi, sh);
   1914             tcg_gen_shli_i64(t1, lo, sh);
   1915             tcg_gen_or_i64(hi, t0, hi);
   1916             tcg_gen_or_i64(lo, t1, lo);
   1917         }
   1918     }
   1919 
   1920     tcg_gen_andi_i64(hi, hi, ~(~0ULL >> nbits));
   1921     tcg_gen_andi_i64(lo, lo, ~(~0ULL >> nbits));
   1922     tcg_gen_shri_i64(lo, lo, nbits);
   1923     tcg_gen_or_i64(hi, hi, lo);
   1924     tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], hi);
   1925 
   1926     tcg_temp_free_i64(hi);
   1927     tcg_temp_free_i64(lo);
   1928     tcg_temp_free_i64(t0);
   1929     tcg_temp_free_i64(t1);
   1930 
   1931     return true;
   1932 }
   1933 
   1934 static bool do_vextdx(DisasContext *ctx, arg_VA *a, int size, bool right,
   1935                void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv))
   1936 {
   1937     TCGv_ptr vrt, vra, vrb;
   1938     TCGv rc;
   1939 
   1940     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1941     REQUIRE_VECTOR(ctx);
   1942 
   1943     vrt = gen_avr_ptr(a->vrt);
   1944     vra = gen_avr_ptr(a->vra);
   1945     vrb = gen_avr_ptr(a->vrb);
   1946     rc = tcg_temp_new();
   1947 
   1948     tcg_gen_andi_tl(rc, cpu_gpr[a->rc], 0x1F);
   1949     if (right) {
   1950         tcg_gen_subfi_tl(rc, 32 - size, rc);
   1951     }
   1952     gen_helper(cpu_env, vrt, vra, vrb, rc);
   1953 
   1954     tcg_temp_free_ptr(vrt);
   1955     tcg_temp_free_ptr(vra);
   1956     tcg_temp_free_ptr(vrb);
   1957     tcg_temp_free(rc);
   1958     return true;
   1959 }
   1960 
   1961 TRANS(VEXTDUBVLX, do_vextdx, 1, false, gen_helper_VEXTDUBVLX)
   1962 TRANS(VEXTDUHVLX, do_vextdx, 2, false, gen_helper_VEXTDUHVLX)
   1963 TRANS(VEXTDUWVLX, do_vextdx, 4, false, gen_helper_VEXTDUWVLX)
   1964 TRANS(VEXTDDVLX, do_vextdx, 8, false, gen_helper_VEXTDDVLX)
   1965 
   1966 TRANS(VEXTDUBVRX, do_vextdx, 1, true, gen_helper_VEXTDUBVLX)
   1967 TRANS(VEXTDUHVRX, do_vextdx, 2, true, gen_helper_VEXTDUHVLX)
   1968 TRANS(VEXTDUWVRX, do_vextdx, 4, true, gen_helper_VEXTDUWVLX)
   1969 TRANS(VEXTDDVRX, do_vextdx, 8, true, gen_helper_VEXTDDVLX)
   1970 
   1971 static bool do_vinsx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
   1972             TCGv_i64 rb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   1973 {
   1974     TCGv_ptr t;
   1975     TCGv idx;
   1976 
   1977     t = gen_avr_ptr(vrt);
   1978     idx = tcg_temp_new();
   1979 
   1980     tcg_gen_andi_tl(idx, ra, 0xF);
   1981     if (right) {
   1982         tcg_gen_subfi_tl(idx, 16 - size, idx);
   1983     }
   1984 
   1985     gen_helper(cpu_env, t, rb, idx);
   1986 
   1987     tcg_temp_free_ptr(t);
   1988     tcg_temp_free(idx);
   1989 
   1990     return true;
   1991 }
   1992 
   1993 static bool do_vinsvx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
   1994                 int vrb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   1995 {
   1996     bool ok;
   1997     TCGv_i64 val;
   1998 
   1999     val = tcg_temp_new_i64();
   2000     get_avr64(val, vrb, true);
   2001     ok = do_vinsx(ctx, vrt, size, right, ra, val, gen_helper);
   2002 
   2003     tcg_temp_free_i64(val);
   2004     return ok;
   2005 }
   2006 
   2007 static bool do_vinsx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
   2008                         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   2009 {
   2010     bool ok;
   2011     TCGv_i64 val;
   2012 
   2013     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2014     REQUIRE_VECTOR(ctx);
   2015 
   2016     val = tcg_temp_new_i64();
   2017     tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
   2018 
   2019     ok = do_vinsx(ctx, a->vrt, size, right, cpu_gpr[a->vra], val, gen_helper);
   2020 
   2021     tcg_temp_free_i64(val);
   2022     return ok;
   2023 }
   2024 
   2025 static bool do_vinsvx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
   2026                         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   2027 {
   2028     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2029     REQUIRE_VECTOR(ctx);
   2030 
   2031     return do_vinsvx(ctx, a->vrt, size, right, cpu_gpr[a->vra], a->vrb,
   2032                      gen_helper);
   2033 }
   2034 
   2035 static bool do_vins_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
   2036                         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   2037 {
   2038     bool ok;
   2039     TCGv_i64 val;
   2040 
   2041     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2042     REQUIRE_VECTOR(ctx);
   2043 
   2044     if (a->uim > (16 - size)) {
   2045         /*
   2046          * PowerISA v3.1 says that the resulting value is undefined in this
   2047          * case, so just log a guest error and leave VRT unchanged. The
   2048          * real hardware would do a partial insert, e.g. if VRT is zeroed and
   2049          * RB is 0x12345678, executing "vinsw VRT,RB,14" results in
   2050          * VRT = 0x0000...00001234, but we don't bother to reproduce this
   2051          * behavior as software shouldn't rely on it.
   2052          */
   2053         qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINS* at"
   2054             " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
   2055             16 - size);
   2056         return true;
   2057     }
   2058 
   2059     val = tcg_temp_new_i64();
   2060     tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
   2061 
   2062     ok = do_vinsx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), val,
   2063                   gen_helper);
   2064 
   2065     tcg_temp_free_i64(val);
   2066     return ok;
   2067 }
   2068 
   2069 static bool do_vinsert_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
   2070                         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
   2071 {
   2072     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2073     REQUIRE_VECTOR(ctx);
   2074 
   2075     if (a->uim > (16 - size)) {
   2076         qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINSERT* at"
   2077             " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
   2078             16 - size);
   2079         return true;
   2080     }
   2081 
   2082     return do_vinsvx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), a->vrb,
   2083                      gen_helper);
   2084 }
   2085 
   2086 TRANS(VINSBLX, do_vinsx_VX, 1, false, gen_helper_VINSBLX)
   2087 TRANS(VINSHLX, do_vinsx_VX, 2, false, gen_helper_VINSHLX)
   2088 TRANS(VINSWLX, do_vinsx_VX, 4, false, gen_helper_VINSWLX)
   2089 TRANS(VINSDLX, do_vinsx_VX, 8, false, gen_helper_VINSDLX)
   2090 
   2091 TRANS(VINSBRX, do_vinsx_VX, 1, true, gen_helper_VINSBLX)
   2092 TRANS(VINSHRX, do_vinsx_VX, 2, true, gen_helper_VINSHLX)
   2093 TRANS(VINSWRX, do_vinsx_VX, 4, true, gen_helper_VINSWLX)
   2094 TRANS(VINSDRX, do_vinsx_VX, 8, true, gen_helper_VINSDLX)
   2095 
   2096 TRANS(VINSW, do_vins_VX_uim4, 4, gen_helper_VINSWLX)
   2097 TRANS(VINSD, do_vins_VX_uim4, 8, gen_helper_VINSDLX)
   2098 
   2099 TRANS(VINSBVLX, do_vinsvx_VX, 1, false, gen_helper_VINSBLX)
   2100 TRANS(VINSHVLX, do_vinsvx_VX, 2, false, gen_helper_VINSHLX)
   2101 TRANS(VINSWVLX, do_vinsvx_VX, 4, false, gen_helper_VINSWLX)
   2102 
   2103 TRANS(VINSBVRX, do_vinsvx_VX, 1, true, gen_helper_VINSBLX)
   2104 TRANS(VINSHVRX, do_vinsvx_VX, 2, true, gen_helper_VINSHLX)
   2105 TRANS(VINSWVRX, do_vinsvx_VX, 4, true, gen_helper_VINSWLX)
   2106 
   2107 TRANS(VINSERTB, do_vinsert_VX_uim4, 1, gen_helper_VINSBLX)
   2108 TRANS(VINSERTH, do_vinsert_VX_uim4, 2, gen_helper_VINSHLX)
   2109 TRANS(VINSERTW, do_vinsert_VX_uim4, 4, gen_helper_VINSWLX)
   2110 TRANS(VINSERTD, do_vinsert_VX_uim4, 8, gen_helper_VINSDLX)
   2111 
   2112 static void gen_vsldoi(DisasContext *ctx)
   2113 {
   2114     TCGv_ptr ra, rb, rd;
   2115     TCGv_i32 sh;
   2116     if (unlikely(!ctx->altivec_enabled)) {
   2117         gen_exception(ctx, POWERPC_EXCP_VPU);
   2118         return;
   2119     }
   2120     ra = gen_avr_ptr(rA(ctx->opcode));
   2121     rb = gen_avr_ptr(rB(ctx->opcode));
   2122     rd = gen_avr_ptr(rD(ctx->opcode));
   2123     sh = tcg_const_i32(VSH(ctx->opcode));
   2124     gen_helper_vsldoi(rd, ra, rb, sh);
   2125     tcg_temp_free_ptr(ra);
   2126     tcg_temp_free_ptr(rb);
   2127     tcg_temp_free_ptr(rd);
   2128     tcg_temp_free_i32(sh);
   2129 }
   2130 
   2131 static bool trans_VSLDBI(DisasContext *ctx, arg_VN *a)
   2132 {
   2133     TCGv_i64 t0, t1, t2;
   2134 
   2135     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2136     REQUIRE_VECTOR(ctx);
   2137 
   2138     t0 = tcg_temp_new_i64();
   2139     t1 = tcg_temp_new_i64();
   2140 
   2141     get_avr64(t0, a->vra, true);
   2142     get_avr64(t1, a->vra, false);
   2143 
   2144     if (a->sh != 0) {
   2145         t2 = tcg_temp_new_i64();
   2146 
   2147         get_avr64(t2, a->vrb, true);
   2148 
   2149         tcg_gen_extract2_i64(t0, t1, t0, 64 - a->sh);
   2150         tcg_gen_extract2_i64(t1, t2, t1, 64 - a->sh);
   2151 
   2152         tcg_temp_free_i64(t2);
   2153     }
   2154 
   2155     set_avr64(a->vrt, t0, true);
   2156     set_avr64(a->vrt, t1, false);
   2157 
   2158     tcg_temp_free_i64(t0);
   2159     tcg_temp_free_i64(t1);
   2160 
   2161     return true;
   2162 }
   2163 
   2164 static bool trans_VSRDBI(DisasContext *ctx, arg_VN *a)
   2165 {
   2166     TCGv_i64 t2, t1, t0;
   2167 
   2168     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2169     REQUIRE_VECTOR(ctx);
   2170 
   2171     t0 = tcg_temp_new_i64();
   2172     t1 = tcg_temp_new_i64();
   2173 
   2174     get_avr64(t0, a->vrb, false);
   2175     get_avr64(t1, a->vrb, true);
   2176 
   2177     if (a->sh != 0) {
   2178         t2 = tcg_temp_new_i64();
   2179 
   2180         get_avr64(t2, a->vra, false);
   2181 
   2182         tcg_gen_extract2_i64(t0, t0, t1, a->sh);
   2183         tcg_gen_extract2_i64(t1, t1, t2, a->sh);
   2184 
   2185         tcg_temp_free_i64(t2);
   2186     }
   2187 
   2188     set_avr64(a->vrt, t0, false);
   2189     set_avr64(a->vrt, t1, true);
   2190 
   2191     tcg_temp_free_i64(t0);
   2192     tcg_temp_free_i64(t1);
   2193 
   2194     return true;
   2195 }
   2196 
   2197 static bool do_vexpand(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
   2198 {
   2199     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2200     REQUIRE_VECTOR(ctx);
   2201 
   2202     tcg_gen_gvec_sari(vece, avr_full_offset(a->vrt), avr_full_offset(a->vrb),
   2203                       (8 << vece) - 1, 16, 16);
   2204 
   2205     return true;
   2206 }
   2207 
   2208 TRANS(VEXPANDBM, do_vexpand, MO_8)
   2209 TRANS(VEXPANDHM, do_vexpand, MO_16)
   2210 TRANS(VEXPANDWM, do_vexpand, MO_32)
   2211 TRANS(VEXPANDDM, do_vexpand, MO_64)
   2212 
   2213 static bool trans_VEXPANDQM(DisasContext *ctx, arg_VX_tb *a)
   2214 {
   2215     TCGv_i64 tmp;
   2216 
   2217     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2218     REQUIRE_VECTOR(ctx);
   2219 
   2220     tmp = tcg_temp_new_i64();
   2221 
   2222     get_avr64(tmp, a->vrb, true);
   2223     tcg_gen_sari_i64(tmp, tmp, 63);
   2224     set_avr64(a->vrt, tmp, false);
   2225     set_avr64(a->vrt, tmp, true);
   2226 
   2227     tcg_temp_free_i64(tmp);
   2228     return true;
   2229 }
   2230 
   2231 static bool do_vextractm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
   2232 {
   2233     const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece,
   2234                    mask = dup_const(vece, 1 << (elem_width - 1));
   2235     uint64_t i, j;
   2236     TCGv_i64 lo, hi, t0, t1;
   2237 
   2238     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2239     REQUIRE_VECTOR(ctx);
   2240 
   2241     hi = tcg_temp_new_i64();
   2242     lo = tcg_temp_new_i64();
   2243     t0 = tcg_temp_new_i64();
   2244     t1 = tcg_temp_new_i64();
   2245 
   2246     get_avr64(lo, a->vrb, false);
   2247     get_avr64(hi, a->vrb, true);
   2248 
   2249     tcg_gen_andi_i64(lo, lo, mask);
   2250     tcg_gen_andi_i64(hi, hi, mask);
   2251 
   2252     /*
   2253      * Gather the most significant bit of each element in the highest element
   2254      * element. E.g. for bytes:
   2255      * aXXXXXXXbXXXXXXXcXXXXXXXdXXXXXXXeXXXXXXXfXXXXXXXgXXXXXXXhXXXXXXX
   2256      *     & dup(1 << (elem_width - 1))
   2257      * a0000000b0000000c0000000d0000000e0000000f0000000g0000000h0000000
   2258      *     << 32 - 4
   2259      * 0000e0000000f0000000g0000000h00000000000000000000000000000000000
   2260      *     |
   2261      * a000e000b000f000c000g000d000h000e0000000f0000000g0000000h0000000
   2262      *     << 16 - 2
   2263      * 00c000g000d000h000e0000000f0000000g0000000h000000000000000000000
   2264      *     |
   2265      * a0c0e0g0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h0000000
   2266      *     << 8 - 1
   2267      * 0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h00000000000000
   2268      *     |
   2269      * abcdefghbcdefgh0cdefgh00defgh000efgh0000fgh00000gh000000h0000000
   2270      */
   2271     for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
   2272         tcg_gen_shli_i64(t0, hi, j - i);
   2273         tcg_gen_shli_i64(t1, lo, j - i);
   2274         tcg_gen_or_i64(hi, hi, t0);
   2275         tcg_gen_or_i64(lo, lo, t1);
   2276     }
   2277 
   2278     tcg_gen_shri_i64(hi, hi, 64 - elem_count_half);
   2279     tcg_gen_extract2_i64(lo, lo, hi, 64 - elem_count_half);
   2280     tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], lo);
   2281 
   2282     tcg_temp_free_i64(hi);
   2283     tcg_temp_free_i64(lo);
   2284     tcg_temp_free_i64(t0);
   2285     tcg_temp_free_i64(t1);
   2286 
   2287     return true;
   2288 }
   2289 
   2290 TRANS(VEXTRACTBM, do_vextractm, MO_8)
   2291 TRANS(VEXTRACTHM, do_vextractm, MO_16)
   2292 TRANS(VEXTRACTWM, do_vextractm, MO_32)
   2293 TRANS(VEXTRACTDM, do_vextractm, MO_64)
   2294 
   2295 static bool trans_VEXTRACTQM(DisasContext *ctx, arg_VX_tb *a)
   2296 {
   2297     TCGv_i64 tmp;
   2298 
   2299     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2300     REQUIRE_VECTOR(ctx);
   2301 
   2302     tmp = tcg_temp_new_i64();
   2303 
   2304     get_avr64(tmp, a->vrb, true);
   2305     tcg_gen_shri_i64(tmp, tmp, 63);
   2306     tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], tmp);
   2307 
   2308     tcg_temp_free_i64(tmp);
   2309 
   2310     return true;
   2311 }
   2312 
   2313 static bool do_mtvsrm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
   2314 {
   2315     const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece;
   2316     uint64_t c;
   2317     int i, j;
   2318     TCGv_i64 hi, lo, t0, t1;
   2319 
   2320     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2321     REQUIRE_VECTOR(ctx);
   2322 
   2323     hi = tcg_temp_new_i64();
   2324     lo = tcg_temp_new_i64();
   2325     t0 = tcg_temp_new_i64();
   2326     t1 = tcg_temp_new_i64();
   2327 
   2328     tcg_gen_extu_tl_i64(t0, cpu_gpr[a->vrb]);
   2329     tcg_gen_extract_i64(hi, t0, elem_count_half, elem_count_half);
   2330     tcg_gen_extract_i64(lo, t0, 0, elem_count_half);
   2331 
   2332     /*
   2333      * Spread the bits into their respective elements.
   2334      * E.g. for bytes:
   2335      * 00000000000000000000000000000000000000000000000000000000abcdefgh
   2336      *   << 32 - 4
   2337      * 0000000000000000000000000000abcdefgh0000000000000000000000000000
   2338      *   |
   2339      * 0000000000000000000000000000abcdefgh00000000000000000000abcdefgh
   2340      *   << 16 - 2
   2341      * 00000000000000abcdefgh00000000000000000000abcdefgh00000000000000
   2342      *   |
   2343      * 00000000000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh
   2344      *   << 8 - 1
   2345      * 0000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh0000000
   2346      *   |
   2347      * 0000000abcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgh
   2348      *   & dup(1)
   2349      * 0000000a0000000b0000000c0000000d0000000e0000000f0000000g0000000h
   2350      *   * 0xff
   2351      * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
   2352      */
   2353     for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
   2354         tcg_gen_shli_i64(t0, hi, j - i);
   2355         tcg_gen_shli_i64(t1, lo, j - i);
   2356         tcg_gen_or_i64(hi, hi, t0);
   2357         tcg_gen_or_i64(lo, lo, t1);
   2358     }
   2359 
   2360     c = dup_const(vece, 1);
   2361     tcg_gen_andi_i64(hi, hi, c);
   2362     tcg_gen_andi_i64(lo, lo, c);
   2363 
   2364     c = MAKE_64BIT_MASK(0, elem_width);
   2365     tcg_gen_muli_i64(hi, hi, c);
   2366     tcg_gen_muli_i64(lo, lo, c);
   2367 
   2368     set_avr64(a->vrt, lo, false);
   2369     set_avr64(a->vrt, hi, true);
   2370 
   2371     tcg_temp_free_i64(hi);
   2372     tcg_temp_free_i64(lo);
   2373     tcg_temp_free_i64(t0);
   2374     tcg_temp_free_i64(t1);
   2375 
   2376     return true;
   2377 }
   2378 
   2379 TRANS(MTVSRBM, do_mtvsrm, MO_8)
   2380 TRANS(MTVSRHM, do_mtvsrm, MO_16)
   2381 TRANS(MTVSRWM, do_mtvsrm, MO_32)
   2382 TRANS(MTVSRDM, do_mtvsrm, MO_64)
   2383 
   2384 static bool trans_MTVSRQM(DisasContext *ctx, arg_VX_tb *a)
   2385 {
   2386     TCGv_i64 tmp;
   2387 
   2388     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2389     REQUIRE_VECTOR(ctx);
   2390 
   2391     tmp = tcg_temp_new_i64();
   2392 
   2393     tcg_gen_ext_tl_i64(tmp, cpu_gpr[a->vrb]);
   2394     tcg_gen_sextract_i64(tmp, tmp, 0, 1);
   2395     set_avr64(a->vrt, tmp, false);
   2396     set_avr64(a->vrt, tmp, true);
   2397 
   2398     tcg_temp_free_i64(tmp);
   2399 
   2400     return true;
   2401 }
   2402 
   2403 static bool trans_MTVSRBMI(DisasContext *ctx, arg_DX_b *a)
   2404 {
   2405     const uint64_t mask = dup_const(MO_8, 1);
   2406     uint64_t hi, lo;
   2407 
   2408     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2409     REQUIRE_VECTOR(ctx);
   2410 
   2411     hi = extract16(a->b, 8, 8);
   2412     lo = extract16(a->b, 0, 8);
   2413 
   2414     for (int i = 4, j = 32; i > 0; i >>= 1, j >>= 1) {
   2415         hi |= hi << (j - i);
   2416         lo |= lo << (j - i);
   2417     }
   2418 
   2419     hi = (hi & mask) * 0xFF;
   2420     lo = (lo & mask) * 0xFF;
   2421 
   2422     set_avr64(a->vrt, tcg_constant_i64(hi), true);
   2423     set_avr64(a->vrt, tcg_constant_i64(lo), false);
   2424 
   2425     return true;
   2426 }
   2427 
   2428 static bool do_vcntmb(DisasContext *ctx, arg_VX_mp *a, int vece)
   2429 {
   2430     TCGv_i64 rt, vrb, mask;
   2431     rt = tcg_const_i64(0);
   2432     vrb = tcg_temp_new_i64();
   2433     mask = tcg_constant_i64(dup_const(vece, 1ULL << ((8 << vece) - 1)));
   2434 
   2435     for (int i = 0; i < 2; i++) {
   2436         get_avr64(vrb, a->vrb, i);
   2437         if (a->mp) {
   2438             tcg_gen_and_i64(vrb, mask, vrb);
   2439         } else {
   2440             tcg_gen_andc_i64(vrb, mask, vrb);
   2441         }
   2442         tcg_gen_ctpop_i64(vrb, vrb);
   2443         tcg_gen_add_i64(rt, rt, vrb);
   2444     }
   2445 
   2446     tcg_gen_shli_i64(rt, rt, TARGET_LONG_BITS - 8 + vece);
   2447     tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], rt);
   2448 
   2449     tcg_temp_free_i64(vrb);
   2450     tcg_temp_free_i64(rt);
   2451 
   2452     return true;
   2453 }
   2454 
   2455 TRANS(VCNTMBB, do_vcntmb, MO_8)
   2456 TRANS(VCNTMBH, do_vcntmb, MO_16)
   2457 TRANS(VCNTMBW, do_vcntmb, MO_32)
   2458 TRANS(VCNTMBD, do_vcntmb, MO_64)
   2459 
   2460 static bool do_vstri(DisasContext *ctx, arg_VX_tb_rc *a,
   2461                      void (*gen_helper)(TCGv_i32, TCGv_ptr, TCGv_ptr))
   2462 {
   2463     TCGv_ptr vrt, vrb;
   2464 
   2465     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2466     REQUIRE_VECTOR(ctx);
   2467 
   2468     vrt = gen_avr_ptr(a->vrt);
   2469     vrb = gen_avr_ptr(a->vrb);
   2470 
   2471     if (a->rc) {
   2472         gen_helper(cpu_crf[6], vrt, vrb);
   2473     } else {
   2474         TCGv_i32 discard = tcg_temp_new_i32();
   2475         gen_helper(discard, vrt, vrb);
   2476         tcg_temp_free_i32(discard);
   2477     }
   2478 
   2479     tcg_temp_free_ptr(vrt);
   2480     tcg_temp_free_ptr(vrb);
   2481 
   2482     return true;
   2483 }
   2484 
   2485 TRANS(VSTRIBL, do_vstri, gen_helper_VSTRIBL)
   2486 TRANS(VSTRIBR, do_vstri, gen_helper_VSTRIBR)
   2487 TRANS(VSTRIHL, do_vstri, gen_helper_VSTRIHL)
   2488 TRANS(VSTRIHR, do_vstri, gen_helper_VSTRIHR)
   2489 
   2490 static bool do_vclrb(DisasContext *ctx, arg_VX *a, bool right)
   2491 {
   2492     TCGv_i64 rb, mh, ml, tmp,
   2493              ones = tcg_constant_i64(-1),
   2494              zero = tcg_constant_i64(0);
   2495 
   2496     rb = tcg_temp_new_i64();
   2497     mh = tcg_temp_new_i64();
   2498     ml = tcg_temp_new_i64();
   2499     tmp = tcg_temp_new_i64();
   2500 
   2501     tcg_gen_extu_tl_i64(rb, cpu_gpr[a->vrb]);
   2502     tcg_gen_andi_i64(tmp, rb, 7);
   2503     tcg_gen_shli_i64(tmp, tmp, 3);
   2504     if (right) {
   2505         tcg_gen_shr_i64(tmp, ones, tmp);
   2506     } else {
   2507         tcg_gen_shl_i64(tmp, ones, tmp);
   2508     }
   2509     tcg_gen_not_i64(tmp, tmp);
   2510 
   2511     if (right) {
   2512         tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
   2513                             tmp, ones);
   2514         tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
   2515                             zero, tmp);
   2516         tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(16),
   2517                             ml, ones);
   2518     } else {
   2519         tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
   2520                             tmp, ones);
   2521         tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
   2522                             zero, tmp);
   2523         tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(16),
   2524                             mh, ones);
   2525     }
   2526 
   2527     get_avr64(tmp, a->vra, true);
   2528     tcg_gen_and_i64(tmp, tmp, mh);
   2529     set_avr64(a->vrt, tmp, true);
   2530 
   2531     get_avr64(tmp, a->vra, false);
   2532     tcg_gen_and_i64(tmp, tmp, ml);
   2533     set_avr64(a->vrt, tmp, false);
   2534 
   2535     tcg_temp_free_i64(rb);
   2536     tcg_temp_free_i64(mh);
   2537     tcg_temp_free_i64(ml);
   2538     tcg_temp_free_i64(tmp);
   2539 
   2540     return true;
   2541 }
   2542 
   2543 TRANS(VCLRLB, do_vclrb, false)
   2544 TRANS(VCLRRB, do_vclrb, true)
   2545 
   2546 #define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
   2547 static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
   2548     {                                                                   \
   2549         TCGv_ptr ra, rb, rc, rd;                                        \
   2550         if (unlikely(!ctx->altivec_enabled)) {                          \
   2551             gen_exception(ctx, POWERPC_EXCP_VPU);                       \
   2552             return;                                                     \
   2553         }                                                               \
   2554         ra = gen_avr_ptr(rA(ctx->opcode));                              \
   2555         rb = gen_avr_ptr(rB(ctx->opcode));                              \
   2556         rc = gen_avr_ptr(rC(ctx->opcode));                              \
   2557         rd = gen_avr_ptr(rD(ctx->opcode));                              \
   2558         if (Rc(ctx->opcode)) {                                          \
   2559             gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
   2560         } else {                                                        \
   2561             gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
   2562         }                                                               \
   2563         tcg_temp_free_ptr(ra);                                          \
   2564         tcg_temp_free_ptr(rb);                                          \
   2565         tcg_temp_free_ptr(rc);                                          \
   2566         tcg_temp_free_ptr(rd);                                          \
   2567     }
   2568 
   2569 GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
   2570 
   2571 static bool do_va_helper(DisasContext *ctx, arg_VA *a,
   2572     void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   2573 {
   2574     TCGv_ptr vrt, vra, vrb, vrc;
   2575     REQUIRE_VECTOR(ctx);
   2576 
   2577     vrt = gen_avr_ptr(a->vrt);
   2578     vra = gen_avr_ptr(a->vra);
   2579     vrb = gen_avr_ptr(a->vrb);
   2580     vrc = gen_avr_ptr(a->rc);
   2581     gen_helper(vrt, vra, vrb, vrc);
   2582     tcg_temp_free_ptr(vrt);
   2583     tcg_temp_free_ptr(vra);
   2584     tcg_temp_free_ptr(vrb);
   2585     tcg_temp_free_ptr(vrc);
   2586 
   2587     return true;
   2588 }
   2589 
   2590 TRANS_FLAGS2(ALTIVEC_207, VADDECUQ, do_va_helper, gen_helper_VADDECUQ)
   2591 TRANS_FLAGS2(ALTIVEC_207, VADDEUQM, do_va_helper, gen_helper_VADDEUQM)
   2592 
   2593 TRANS_FLAGS2(ALTIVEC_207, VSUBEUQM, do_va_helper, gen_helper_VSUBEUQM)
   2594 TRANS_FLAGS2(ALTIVEC_207, VSUBECUQ, do_va_helper, gen_helper_VSUBECUQ)
   2595 
   2596 TRANS_FLAGS(ALTIVEC, VPERM, do_va_helper, gen_helper_VPERM)
   2597 TRANS_FLAGS2(ISA300, VPERMR, do_va_helper, gen_helper_VPERMR)
   2598 
   2599 static void gen_vmladduhm_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
   2600                               TCGv_vec c)
   2601 {
   2602     tcg_gen_mul_vec(vece, t, a, b);
   2603     tcg_gen_add_vec(vece, t, t, c);
   2604 }
   2605 
   2606 static bool trans_VMLADDUHM(DisasContext *ctx, arg_VA *a)
   2607 {
   2608     static const TCGOpcode vecop_list[] = {
   2609         INDEX_op_add_vec, INDEX_op_mul_vec, 0
   2610     };
   2611 
   2612     static const GVecGen4 op = {
   2613         .fno = gen_helper_VMLADDUHM,
   2614         .fniv = gen_vmladduhm_vec,
   2615         .opt_opc = vecop_list,
   2616         .vece = MO_16
   2617     };
   2618 
   2619     REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
   2620     REQUIRE_VECTOR(ctx);
   2621 
   2622     tcg_gen_gvec_4(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   2623                    avr_full_offset(a->vrb), avr_full_offset(a->rc),
   2624                    16, 16, &op);
   2625 
   2626     return true;
   2627 }
   2628 
   2629 static bool trans_VSEL(DisasContext *ctx, arg_VA *a)
   2630 {
   2631     REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
   2632     REQUIRE_VECTOR(ctx);
   2633 
   2634     tcg_gen_gvec_bitsel(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->rc),
   2635                         avr_full_offset(a->vrb), avr_full_offset(a->vra),
   2636                         16, 16);
   2637 
   2638     return true;
   2639 }
   2640 
   2641 TRANS_FLAGS(ALTIVEC, VMSUMUBM, do_va_helper, gen_helper_VMSUMUBM)
   2642 TRANS_FLAGS(ALTIVEC, VMSUMMBM, do_va_helper, gen_helper_VMSUMMBM)
   2643 TRANS_FLAGS(ALTIVEC, VMSUMSHM, do_va_helper, gen_helper_VMSUMSHM)
   2644 TRANS_FLAGS(ALTIVEC, VMSUMUHM, do_va_helper, gen_helper_VMSUMUHM)
   2645 
   2646 static bool do_va_env_helper(DisasContext *ctx, arg_VA *a,
   2647     void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   2648 {
   2649     TCGv_ptr vrt, vra, vrb, vrc;
   2650     REQUIRE_VECTOR(ctx);
   2651 
   2652     vrt = gen_avr_ptr(a->vrt);
   2653     vra = gen_avr_ptr(a->vra);
   2654     vrb = gen_avr_ptr(a->vrb);
   2655     vrc = gen_avr_ptr(a->rc);
   2656     gen_helper(cpu_env, vrt, vra, vrb, vrc);
   2657     tcg_temp_free_ptr(vrt);
   2658     tcg_temp_free_ptr(vra);
   2659     tcg_temp_free_ptr(vrb);
   2660     tcg_temp_free_ptr(vrc);
   2661 
   2662     return true;
   2663 }
   2664 
   2665 TRANS_FLAGS(ALTIVEC, VMSUMUHS, do_va_env_helper, gen_helper_VMSUMUHS)
   2666 TRANS_FLAGS(ALTIVEC, VMSUMSHS, do_va_env_helper, gen_helper_VMSUMSHS)
   2667 
   2668 TRANS_FLAGS(ALTIVEC, VMHADDSHS, do_va_env_helper, gen_helper_VMHADDSHS)
   2669 TRANS_FLAGS(ALTIVEC, VMHRADDSHS, do_va_env_helper, gen_helper_VMHRADDSHS)
   2670 
   2671 GEN_VXFORM_NOA(vclzb, 1, 28)
   2672 GEN_VXFORM_NOA(vclzh, 1, 29)
   2673 GEN_VXFORM_TRANS(vclzw, 1, 30)
   2674 GEN_VXFORM_TRANS(vclzd, 1, 31)
   2675 
   2676 static bool do_vneg(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
   2677 {
   2678     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2679     REQUIRE_VECTOR(ctx);
   2680 
   2681     tcg_gen_gvec_neg(vece, avr_full_offset(a->vrt), avr_full_offset(a->vrb),
   2682                      16, 16);
   2683     return true;
   2684 }
   2685 
   2686 TRANS(VNEGW, do_vneg, MO_32)
   2687 TRANS(VNEGD, do_vneg, MO_64)
   2688 
   2689 static void gen_vexts_i64(TCGv_i64 t, TCGv_i64 b, int64_t s)
   2690 {
   2691     tcg_gen_sextract_i64(t, b, 0, 64 - s);
   2692 }
   2693 
   2694 static void gen_vexts_i32(TCGv_i32 t, TCGv_i32 b, int32_t s)
   2695 {
   2696     tcg_gen_sextract_i32(t, b, 0, 32 - s);
   2697 }
   2698 
   2699 static void gen_vexts_vec(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t s)
   2700 {
   2701     tcg_gen_shli_vec(vece, t, b, s);
   2702     tcg_gen_sari_vec(vece, t, t, s);
   2703 }
   2704 
   2705 static bool do_vexts(DisasContext *ctx, arg_VX_tb *a, unsigned vece, int64_t s)
   2706 {
   2707     static const TCGOpcode vecop_list[] = {
   2708         INDEX_op_shli_vec, INDEX_op_sari_vec, 0
   2709     };
   2710 
   2711     static const GVecGen2i op[2] = {
   2712         {
   2713             .fni4 = gen_vexts_i32,
   2714             .fniv = gen_vexts_vec,
   2715             .opt_opc = vecop_list,
   2716             .vece = MO_32
   2717         },
   2718         {
   2719             .fni8 = gen_vexts_i64,
   2720             .fniv = gen_vexts_vec,
   2721             .opt_opc = vecop_list,
   2722             .vece = MO_64
   2723         },
   2724     };
   2725 
   2726     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2727     REQUIRE_VECTOR(ctx);
   2728 
   2729     tcg_gen_gvec_2i(avr_full_offset(a->vrt), avr_full_offset(a->vrb),
   2730                     16, 16, s, &op[vece - MO_32]);
   2731 
   2732     return true;
   2733 }
   2734 
   2735 TRANS(VEXTSB2W, do_vexts, MO_32, 24);
   2736 TRANS(VEXTSH2W, do_vexts, MO_32, 16);
   2737 TRANS(VEXTSB2D, do_vexts, MO_64, 56);
   2738 TRANS(VEXTSH2D, do_vexts, MO_64, 48);
   2739 TRANS(VEXTSW2D, do_vexts, MO_64, 32);
   2740 
   2741 static bool trans_VEXTSD2Q(DisasContext *ctx, arg_VX_tb *a)
   2742 {
   2743     TCGv_i64 tmp;
   2744 
   2745     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2746     REQUIRE_VECTOR(ctx);
   2747 
   2748     tmp = tcg_temp_new_i64();
   2749 
   2750     get_avr64(tmp, a->vrb, false);
   2751     set_avr64(a->vrt, tmp, false);
   2752     tcg_gen_sari_i64(tmp, tmp, 63);
   2753     set_avr64(a->vrt, tmp, true);
   2754 
   2755     tcg_temp_free_i64(tmp);
   2756     return true;
   2757 }
   2758 
   2759 GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
   2760 GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
   2761 GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
   2762 GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
   2763 GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
   2764 GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
   2765 GEN_VXFORM_NOA(vpopcntb, 1, 28)
   2766 GEN_VXFORM_NOA(vpopcnth, 1, 29)
   2767 GEN_VXFORM_NOA(vpopcntw, 1, 30)
   2768 GEN_VXFORM_NOA(vpopcntd, 1, 31)
   2769 GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
   2770                 vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
   2771 GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
   2772                 vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
   2773 GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
   2774                 vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
   2775 GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
   2776                 vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
   2777 GEN_VXFORM(vbpermd, 6, 23);
   2778 GEN_VXFORM(vbpermq, 6, 21);
   2779 GEN_VXFORM_TRANS(vgbbd, 6, 20);
   2780 GEN_VXFORM(vpmsumb, 4, 16)
   2781 GEN_VXFORM(vpmsumh, 4, 17)
   2782 GEN_VXFORM(vpmsumw, 4, 18)
   2783 
   2784 #define GEN_BCD(op)                                 \
   2785 static void gen_##op(DisasContext *ctx)             \
   2786 {                                                   \
   2787     TCGv_ptr ra, rb, rd;                            \
   2788     TCGv_i32 ps;                                    \
   2789                                                     \
   2790     if (unlikely(!ctx->altivec_enabled)) {          \
   2791         gen_exception(ctx, POWERPC_EXCP_VPU);       \
   2792         return;                                     \
   2793     }                                               \
   2794                                                     \
   2795     ra = gen_avr_ptr(rA(ctx->opcode));              \
   2796     rb = gen_avr_ptr(rB(ctx->opcode));              \
   2797     rd = gen_avr_ptr(rD(ctx->opcode));              \
   2798                                                     \
   2799     ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
   2800                                                     \
   2801     gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
   2802                                                     \
   2803     tcg_temp_free_ptr(ra);                          \
   2804     tcg_temp_free_ptr(rb);                          \
   2805     tcg_temp_free_ptr(rd);                          \
   2806     tcg_temp_free_i32(ps);                          \
   2807 }
   2808 
   2809 #define GEN_BCD2(op)                                \
   2810 static void gen_##op(DisasContext *ctx)             \
   2811 {                                                   \
   2812     TCGv_ptr rd, rb;                                \
   2813     TCGv_i32 ps;                                    \
   2814                                                     \
   2815     if (unlikely(!ctx->altivec_enabled)) {          \
   2816         gen_exception(ctx, POWERPC_EXCP_VPU);       \
   2817         return;                                     \
   2818     }                                               \
   2819                                                     \
   2820     rb = gen_avr_ptr(rB(ctx->opcode));              \
   2821     rd = gen_avr_ptr(rD(ctx->opcode));              \
   2822                                                     \
   2823     ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
   2824                                                     \
   2825     gen_helper_##op(cpu_crf[6], rd, rb, ps);        \
   2826                                                     \
   2827     tcg_temp_free_ptr(rb);                          \
   2828     tcg_temp_free_ptr(rd);                          \
   2829     tcg_temp_free_i32(ps);                          \
   2830 }
   2831 
   2832 GEN_BCD(bcdadd)
   2833 GEN_BCD(bcdsub)
   2834 GEN_BCD2(bcdcfn)
   2835 GEN_BCD2(bcdctn)
   2836 GEN_BCD2(bcdcfz)
   2837 GEN_BCD2(bcdctz)
   2838 GEN_BCD2(bcdcfsq)
   2839 GEN_BCD2(bcdctsq)
   2840 GEN_BCD2(bcdsetsgn)
   2841 GEN_BCD(bcdcpsgn);
   2842 GEN_BCD(bcds);
   2843 GEN_BCD(bcdus);
   2844 GEN_BCD(bcdsr);
   2845 GEN_BCD(bcdtrunc);
   2846 GEN_BCD(bcdutrunc);
   2847 
   2848 static void gen_xpnd04_1(DisasContext *ctx)
   2849 {
   2850     switch (opc4(ctx->opcode)) {
   2851     case 0:
   2852         gen_bcdctsq(ctx);
   2853         break;
   2854     case 2:
   2855         gen_bcdcfsq(ctx);
   2856         break;
   2857     case 4:
   2858         gen_bcdctz(ctx);
   2859         break;
   2860     case 5:
   2861         gen_bcdctn(ctx);
   2862         break;
   2863     case 6:
   2864         gen_bcdcfz(ctx);
   2865         break;
   2866     case 7:
   2867         gen_bcdcfn(ctx);
   2868         break;
   2869     case 31:
   2870         gen_bcdsetsgn(ctx);
   2871         break;
   2872     default:
   2873         gen_invalid(ctx);
   2874         break;
   2875     }
   2876 }
   2877 
   2878 static void gen_xpnd04_2(DisasContext *ctx)
   2879 {
   2880     switch (opc4(ctx->opcode)) {
   2881     case 0:
   2882         gen_bcdctsq(ctx);
   2883         break;
   2884     case 2:
   2885         gen_bcdcfsq(ctx);
   2886         break;
   2887     case 4:
   2888         gen_bcdctz(ctx);
   2889         break;
   2890     case 6:
   2891         gen_bcdcfz(ctx);
   2892         break;
   2893     case 7:
   2894         gen_bcdcfn(ctx);
   2895         break;
   2896     case 31:
   2897         gen_bcdsetsgn(ctx);
   2898         break;
   2899     default:
   2900         gen_invalid(ctx);
   2901         break;
   2902     }
   2903 }
   2904 
   2905 
   2906 GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \
   2907                 xpnd04_2, PPC_NONE, PPC2_ISA300)
   2908 
   2909 GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
   2910                 bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
   2911 GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
   2912                 bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
   2913 GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
   2914                 bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
   2915 GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
   2916                 bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
   2917 GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \
   2918                 bcdcpsgn, PPC_NONE, PPC2_ISA300)
   2919 GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
   2920                 bcds, PPC_NONE, PPC2_ISA300)
   2921 GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
   2922                 bcdus, PPC_NONE, PPC2_ISA300)
   2923 GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
   2924                 bcdtrunc, PPC_NONE, PPC2_ISA300)
   2925 
   2926 static void gen_vsbox(DisasContext *ctx)
   2927 {
   2928     TCGv_ptr ra, rd;
   2929     if (unlikely(!ctx->altivec_enabled)) {
   2930         gen_exception(ctx, POWERPC_EXCP_VPU);
   2931         return;
   2932     }
   2933     ra = gen_avr_ptr(rA(ctx->opcode));
   2934     rd = gen_avr_ptr(rD(ctx->opcode));
   2935     gen_helper_vsbox(rd, ra);
   2936     tcg_temp_free_ptr(ra);
   2937     tcg_temp_free_ptr(rd);
   2938 }
   2939 
   2940 GEN_VXFORM(vcipher, 4, 20)
   2941 GEN_VXFORM(vcipherlast, 4, 20)
   2942 GEN_VXFORM(vncipher, 4, 21)
   2943 GEN_VXFORM(vncipherlast, 4, 21)
   2944 
   2945 GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
   2946                 vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
   2947 GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
   2948                 vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
   2949 
   2950 #define VSHASIGMA(op)                         \
   2951 static void gen_##op(DisasContext *ctx)       \
   2952 {                                             \
   2953     TCGv_ptr ra, rd;                          \
   2954     TCGv_i32 st_six;                          \
   2955     if (unlikely(!ctx->altivec_enabled)) {    \
   2956         gen_exception(ctx, POWERPC_EXCP_VPU); \
   2957         return;                               \
   2958     }                                         \
   2959     ra = gen_avr_ptr(rA(ctx->opcode));        \
   2960     rd = gen_avr_ptr(rD(ctx->opcode));        \
   2961     st_six = tcg_const_i32(rB(ctx->opcode));  \
   2962     gen_helper_##op(rd, ra, st_six);          \
   2963     tcg_temp_free_ptr(ra);                    \
   2964     tcg_temp_free_ptr(rd);                    \
   2965     tcg_temp_free_i32(st_six);                \
   2966 }
   2967 
   2968 VSHASIGMA(vshasigmaw)
   2969 VSHASIGMA(vshasigmad)
   2970 
   2971 GEN_VXFORM3(vpermxor, 22, 0xFF)
   2972 GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
   2973                 vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
   2974 
   2975 static bool trans_VCFUGED(DisasContext *ctx, arg_VX *a)
   2976 {
   2977     static const GVecGen3 g = {
   2978         .fni8 = gen_helper_CFUGED,
   2979         .vece = MO_64,
   2980     };
   2981 
   2982     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2983     REQUIRE_VECTOR(ctx);
   2984 
   2985     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   2986                    avr_full_offset(a->vrb), 16, 16, &g);
   2987 
   2988     return true;
   2989 }
   2990 
   2991 static bool trans_VCLZDM(DisasContext *ctx, arg_VX *a)
   2992 {
   2993     static const GVecGen3i g = {
   2994         .fni8 = do_cntzdm,
   2995         .vece = MO_64,
   2996     };
   2997 
   2998     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2999     REQUIRE_VECTOR(ctx);
   3000 
   3001     tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3002                     avr_full_offset(a->vrb), 16, 16, false, &g);
   3003 
   3004     return true;
   3005 }
   3006 
   3007 static bool trans_VCTZDM(DisasContext *ctx, arg_VX *a)
   3008 {
   3009     static const GVecGen3i g = {
   3010         .fni8 = do_cntzdm,
   3011         .vece = MO_64,
   3012     };
   3013 
   3014     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3015     REQUIRE_VECTOR(ctx);
   3016 
   3017     tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3018                     avr_full_offset(a->vrb), 16, 16, true, &g);
   3019 
   3020     return true;
   3021 }
   3022 
   3023 static bool trans_VPDEPD(DisasContext *ctx, arg_VX *a)
   3024 {
   3025     static const GVecGen3 g = {
   3026         .fni8 = gen_helper_PDEPD,
   3027         .vece = MO_64,
   3028     };
   3029 
   3030     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3031     REQUIRE_VECTOR(ctx);
   3032 
   3033     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3034                    avr_full_offset(a->vrb), 16, 16, &g);
   3035 
   3036     return true;
   3037 }
   3038 
   3039 static bool trans_VPEXTD(DisasContext *ctx, arg_VX *a)
   3040 {
   3041     static const GVecGen3 g = {
   3042         .fni8 = gen_helper_PEXTD,
   3043         .vece = MO_64,
   3044     };
   3045 
   3046     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3047     REQUIRE_VECTOR(ctx);
   3048 
   3049     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3050                    avr_full_offset(a->vrb), 16, 16, &g);
   3051 
   3052     return true;
   3053 }
   3054 
   3055 static bool trans_VMSUMUDM(DisasContext *ctx, arg_VA *a)
   3056 {
   3057     TCGv_i64 rl, rh, src1, src2;
   3058     int dw;
   3059 
   3060     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   3061     REQUIRE_VECTOR(ctx);
   3062 
   3063     rh = tcg_temp_new_i64();
   3064     rl = tcg_temp_new_i64();
   3065     src1 = tcg_temp_new_i64();
   3066     src2 = tcg_temp_new_i64();
   3067 
   3068     get_avr64(rl, a->rc, false);
   3069     get_avr64(rh, a->rc, true);
   3070 
   3071     for (dw = 0; dw < 2; dw++) {
   3072         get_avr64(src1, a->vra, dw);
   3073         get_avr64(src2, a->vrb, dw);
   3074         tcg_gen_mulu2_i64(src1, src2, src1, src2);
   3075         tcg_gen_add2_i64(rl, rh, rl, rh, src1, src2);
   3076     }
   3077 
   3078     set_avr64(a->vrt, rl, false);
   3079     set_avr64(a->vrt, rh, true);
   3080 
   3081     tcg_temp_free_i64(rl);
   3082     tcg_temp_free_i64(rh);
   3083     tcg_temp_free_i64(src1);
   3084     tcg_temp_free_i64(src2);
   3085 
   3086     return true;
   3087 }
   3088 
   3089 static bool trans_VMSUMCUD(DisasContext *ctx, arg_VA *a)
   3090 {
   3091     TCGv_i64 tmp0, tmp1, prod1h, prod1l, prod0h, prod0l, zero;
   3092 
   3093     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3094     REQUIRE_VECTOR(ctx);
   3095 
   3096     tmp0 = tcg_temp_new_i64();
   3097     tmp1 = tcg_temp_new_i64();
   3098     prod1h = tcg_temp_new_i64();
   3099     prod1l = tcg_temp_new_i64();
   3100     prod0h = tcg_temp_new_i64();
   3101     prod0l = tcg_temp_new_i64();
   3102     zero = tcg_constant_i64(0);
   3103 
   3104     /* prod1 = vsr[vra+32].dw[1] * vsr[vrb+32].dw[1] */
   3105     get_avr64(tmp0, a->vra, false);
   3106     get_avr64(tmp1, a->vrb, false);
   3107     tcg_gen_mulu2_i64(prod1l, prod1h, tmp0, tmp1);
   3108 
   3109     /* prod0 = vsr[vra+32].dw[0] * vsr[vrb+32].dw[0] */
   3110     get_avr64(tmp0, a->vra, true);
   3111     get_avr64(tmp1, a->vrb, true);
   3112     tcg_gen_mulu2_i64(prod0l, prod0h, tmp0, tmp1);
   3113 
   3114     /* Sum lower 64-bits elements */
   3115     get_avr64(tmp1, a->rc, false);
   3116     tcg_gen_add2_i64(tmp1, tmp0, tmp1, zero, prod1l, zero);
   3117     tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0l, zero);
   3118 
   3119     /*
   3120      * Discard lower 64-bits, leaving the carry into bit 64.
   3121      * Then sum the higher 64-bit elements.
   3122      */
   3123     get_avr64(tmp1, a->rc, true);
   3124     tcg_gen_add2_i64(tmp1, tmp0, tmp0, zero, tmp1, zero);
   3125     tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod1h, zero);
   3126     tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0h, zero);
   3127 
   3128     /* Discard 64 more bits to complete the CHOP128(temp >> 128) */
   3129     set_avr64(a->vrt, tmp0, false);
   3130     set_avr64(a->vrt, zero, true);
   3131 
   3132     tcg_temp_free_i64(tmp0);
   3133     tcg_temp_free_i64(tmp1);
   3134     tcg_temp_free_i64(prod1h);
   3135     tcg_temp_free_i64(prod1l);
   3136     tcg_temp_free_i64(prod0h);
   3137     tcg_temp_free_i64(prod0l);
   3138 
   3139     return true;
   3140 }
   3141 
   3142 static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
   3143                          void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
   3144 {
   3145     TCGv_ptr ra, rb, rd;
   3146     REQUIRE_VECTOR(ctx);
   3147 
   3148     ra = gen_avr_ptr(a->vra);
   3149     rb = gen_avr_ptr(a->vrb);
   3150     rd = gen_avr_ptr(a->vrt);
   3151     gen_helper(rd, ra, rb);
   3152     tcg_temp_free_ptr(ra);
   3153     tcg_temp_free_ptr(rb);
   3154     tcg_temp_free_ptr(rd);
   3155 
   3156     return true;
   3157 }
   3158 
   3159 TRANS_FLAGS2(ALTIVEC_207, VADDCUQ, do_vx_helper, gen_helper_VADDCUQ)
   3160 TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, gen_helper_VADDUQM)
   3161 
   3162 TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
   3163 
   3164 TRANS_FLAGS2(ALTIVEC_207, VSUBCUQ, do_vx_helper, gen_helper_VSUBCUQ)
   3165 TRANS_FLAGS2(ALTIVEC_207, VSUBUQM, do_vx_helper, gen_helper_VSUBUQM)
   3166 
   3167 static void gen_VADDCUW_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   3168 {
   3169     tcg_gen_not_vec(vece, a, a);
   3170     tcg_gen_cmp_vec(TCG_COND_LTU, vece, t, a, b);
   3171     tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(t, vece, 1));
   3172 }
   3173 
   3174 static void gen_VADDCUW_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
   3175 {
   3176     tcg_gen_not_i32(a, a);
   3177     tcg_gen_setcond_i32(TCG_COND_LTU, t, a, b);
   3178 }
   3179 
   3180 static void gen_VSUBCUW_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   3181 {
   3182     tcg_gen_cmp_vec(TCG_COND_GEU, vece, t, a, b);
   3183     tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(t, vece, 1));
   3184 }
   3185 
   3186 static void gen_VSUBCUW_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
   3187 {
   3188     tcg_gen_setcond_i32(TCG_COND_GEU, t, a, b);
   3189 }
   3190 
   3191 static bool do_vx_vaddsubcuw(DisasContext *ctx, arg_VX *a, int add)
   3192 {
   3193     static const TCGOpcode vecop_list[] = {
   3194         INDEX_op_cmp_vec, 0
   3195     };
   3196 
   3197     static const GVecGen3 op[] = {
   3198         {
   3199             .fniv = gen_VSUBCUW_vec,
   3200             .fni4 = gen_VSUBCUW_i32,
   3201             .opt_opc = vecop_list,
   3202             .vece = MO_32
   3203         },
   3204         {
   3205             .fniv = gen_VADDCUW_vec,
   3206             .fni4 = gen_VADDCUW_i32,
   3207             .opt_opc = vecop_list,
   3208             .vece = MO_32
   3209         },
   3210     };
   3211 
   3212     REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
   3213     REQUIRE_VECTOR(ctx);
   3214 
   3215     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3216                    avr_full_offset(a->vrb), 16, 16, &op[add]);
   3217 
   3218     return true;
   3219 }
   3220 
   3221 TRANS(VSUBCUW, do_vx_vaddsubcuw, 0)
   3222 TRANS(VADDCUW, do_vx_vaddsubcuw, 1)
   3223 
   3224 static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
   3225                          void (*gen_mul)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
   3226 {
   3227     TCGv_i64 vra, vrb, vrt0, vrt1;
   3228     REQUIRE_VECTOR(ctx);
   3229 
   3230     vra = tcg_temp_new_i64();
   3231     vrb = tcg_temp_new_i64();
   3232     vrt0 = tcg_temp_new_i64();
   3233     vrt1 = tcg_temp_new_i64();
   3234 
   3235     get_avr64(vra, a->vra, even);
   3236     get_avr64(vrb, a->vrb, even);
   3237     gen_mul(vrt0, vrt1, vra, vrb);
   3238     set_avr64(a->vrt, vrt0, false);
   3239     set_avr64(a->vrt, vrt1, true);
   3240 
   3241     tcg_temp_free_i64(vra);
   3242     tcg_temp_free_i64(vrb);
   3243     tcg_temp_free_i64(vrt0);
   3244     tcg_temp_free_i64(vrt1);
   3245 
   3246     return true;
   3247 }
   3248 
   3249 static bool trans_VMULLD(DisasContext *ctx, arg_VX *a)
   3250 {
   3251     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3252     REQUIRE_VECTOR(ctx);
   3253 
   3254     tcg_gen_gvec_mul(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3255                      avr_full_offset(a->vrb), 16, 16);
   3256 
   3257     return true;
   3258 }
   3259 
   3260 TRANS_FLAGS(ALTIVEC, VMULESB, do_vx_helper, gen_helper_VMULESB)
   3261 TRANS_FLAGS(ALTIVEC, VMULOSB, do_vx_helper, gen_helper_VMULOSB)
   3262 TRANS_FLAGS(ALTIVEC, VMULEUB, do_vx_helper, gen_helper_VMULEUB)
   3263 TRANS_FLAGS(ALTIVEC, VMULOUB, do_vx_helper, gen_helper_VMULOUB)
   3264 TRANS_FLAGS(ALTIVEC, VMULESH, do_vx_helper, gen_helper_VMULESH)
   3265 TRANS_FLAGS(ALTIVEC, VMULOSH, do_vx_helper, gen_helper_VMULOSH)
   3266 TRANS_FLAGS(ALTIVEC, VMULEUH, do_vx_helper, gen_helper_VMULEUH)
   3267 TRANS_FLAGS(ALTIVEC, VMULOUH, do_vx_helper, gen_helper_VMULOUH)
   3268 TRANS_FLAGS2(ALTIVEC_207, VMULESW, do_vx_helper, gen_helper_VMULESW)
   3269 TRANS_FLAGS2(ALTIVEC_207, VMULOSW, do_vx_helper, gen_helper_VMULOSW)
   3270 TRANS_FLAGS2(ALTIVEC_207, VMULEUW, do_vx_helper, gen_helper_VMULEUW)
   3271 TRANS_FLAGS2(ALTIVEC_207, VMULOUW, do_vx_helper, gen_helper_VMULOUW)
   3272 TRANS_FLAGS2(ISA310, VMULESD, do_vx_vmuleo, true , tcg_gen_muls2_i64)
   3273 TRANS_FLAGS2(ISA310, VMULOSD, do_vx_vmuleo, false, tcg_gen_muls2_i64)
   3274 TRANS_FLAGS2(ISA310, VMULEUD, do_vx_vmuleo, true , tcg_gen_mulu2_i64)
   3275 TRANS_FLAGS2(ISA310, VMULOUD, do_vx_vmuleo, false, tcg_gen_mulu2_i64)
   3276 
   3277 static void do_vx_vmulhw_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
   3278 {
   3279     TCGv_i64 hh, lh, temp;
   3280 
   3281     hh = tcg_temp_new_i64();
   3282     lh = tcg_temp_new_i64();
   3283     temp = tcg_temp_new_i64();
   3284 
   3285     if (sign) {
   3286         tcg_gen_ext32s_i64(lh, a);
   3287         tcg_gen_ext32s_i64(temp, b);
   3288     } else {
   3289         tcg_gen_ext32u_i64(lh, a);
   3290         tcg_gen_ext32u_i64(temp, b);
   3291     }
   3292     tcg_gen_mul_i64(lh, lh, temp);
   3293 
   3294     if (sign) {
   3295         tcg_gen_sari_i64(hh, a, 32);
   3296         tcg_gen_sari_i64(temp, b, 32);
   3297     } else {
   3298         tcg_gen_shri_i64(hh, a, 32);
   3299         tcg_gen_shri_i64(temp, b, 32);
   3300     }
   3301     tcg_gen_mul_i64(hh, hh, temp);
   3302 
   3303     tcg_gen_shri_i64(lh, lh, 32);
   3304     tcg_gen_deposit_i64(t, hh, lh, 0, 32);
   3305 
   3306     tcg_temp_free_i64(hh);
   3307     tcg_temp_free_i64(lh);
   3308     tcg_temp_free_i64(temp);
   3309 }
   3310 
   3311 static void do_vx_vmulhd_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
   3312 {
   3313     TCGv_i64 tlow;
   3314 
   3315     tlow  = tcg_temp_new_i64();
   3316     if (sign) {
   3317         tcg_gen_muls2_i64(tlow, t, a, b);
   3318     } else {
   3319         tcg_gen_mulu2_i64(tlow, t, a, b);
   3320     }
   3321 
   3322     tcg_temp_free_i64(tlow);
   3323 }
   3324 
   3325 static bool do_vx_mulh(DisasContext *ctx, arg_VX *a, bool sign,
   3326                        void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, bool))
   3327 {
   3328     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3329     REQUIRE_VECTOR(ctx);
   3330 
   3331     TCGv_i64 vra, vrb, vrt;
   3332     int i;
   3333 
   3334     vra = tcg_temp_new_i64();
   3335     vrb = tcg_temp_new_i64();
   3336     vrt = tcg_temp_new_i64();
   3337 
   3338     for (i = 0; i < 2; i++) {
   3339         get_avr64(vra, a->vra, i);
   3340         get_avr64(vrb, a->vrb, i);
   3341         get_avr64(vrt, a->vrt, i);
   3342 
   3343         func(vrt, vra, vrb, sign);
   3344 
   3345         set_avr64(a->vrt, vrt, i);
   3346     }
   3347 
   3348     tcg_temp_free_i64(vra);
   3349     tcg_temp_free_i64(vrb);
   3350     tcg_temp_free_i64(vrt);
   3351 
   3352     return true;
   3353 
   3354 }
   3355 
   3356 TRANS(VMULHSW, do_vx_mulh, true , do_vx_vmulhw_i64)
   3357 TRANS(VMULHSD, do_vx_mulh, true , do_vx_vmulhd_i64)
   3358 TRANS(VMULHUW, do_vx_mulh, false, do_vx_vmulhw_i64)
   3359 TRANS(VMULHUD, do_vx_mulh, false, do_vx_vmulhd_i64)
   3360 
   3361 static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
   3362                     void (*gen_shr_vec)(unsigned, TCGv_vec, TCGv_vec, int64_t))
   3363 {
   3364     TCGv_vec tmp = tcg_temp_new_vec_matching(t);
   3365     tcg_gen_or_vec(vece, tmp, a, b);
   3366     tcg_gen_and_vec(vece, tmp, tmp, tcg_constant_vec_matching(t, vece, 1));
   3367     gen_shr_vec(vece, a, a, 1);
   3368     gen_shr_vec(vece, b, b, 1);
   3369     tcg_gen_add_vec(vece, t, a, b);
   3370     tcg_gen_add_vec(vece, t, t, tmp);
   3371     tcg_temp_free_vec(tmp);
   3372 }
   3373 
   3374 QEMU_FLATTEN
   3375 static void gen_vavgu(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   3376 {
   3377     do_vavg(vece, t, a, b, tcg_gen_shri_vec);
   3378 }
   3379 
   3380 QEMU_FLATTEN
   3381 static void gen_vavgs(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   3382 {
   3383     do_vavg(vece, t, a, b, tcg_gen_sari_vec);
   3384 }
   3385 
   3386 static bool do_vx_vavg(DisasContext *ctx, arg_VX *a, int sign, int vece)
   3387 {
   3388     static const TCGOpcode vecop_list_s[] = {
   3389         INDEX_op_add_vec, INDEX_op_sari_vec, 0
   3390     };
   3391     static const TCGOpcode vecop_list_u[] = {
   3392         INDEX_op_add_vec, INDEX_op_shri_vec, 0
   3393     };
   3394 
   3395     static const GVecGen3 op[2][3] = {
   3396         {
   3397             {
   3398                 .fniv = gen_vavgu,
   3399                 .fno = gen_helper_VAVGUB,
   3400                 .opt_opc = vecop_list_u,
   3401                 .vece = MO_8
   3402             },
   3403             {
   3404                 .fniv = gen_vavgu,
   3405                 .fno = gen_helper_VAVGUH,
   3406                 .opt_opc = vecop_list_u,
   3407                 .vece = MO_16
   3408             },
   3409             {
   3410                 .fniv = gen_vavgu,
   3411                 .fno = gen_helper_VAVGUW,
   3412                 .opt_opc = vecop_list_u,
   3413                 .vece = MO_32
   3414             },
   3415         },
   3416         {
   3417             {
   3418                 .fniv = gen_vavgs,
   3419                 .fno = gen_helper_VAVGSB,
   3420                 .opt_opc = vecop_list_s,
   3421                 .vece = MO_8
   3422             },
   3423             {
   3424                 .fniv = gen_vavgs,
   3425                 .fno = gen_helper_VAVGSH,
   3426                 .opt_opc = vecop_list_s,
   3427                 .vece = MO_16
   3428             },
   3429             {
   3430                 .fniv = gen_vavgs,
   3431                 .fno = gen_helper_VAVGSW,
   3432                 .opt_opc = vecop_list_s,
   3433                 .vece = MO_32
   3434             },
   3435         },
   3436     };
   3437 
   3438     REQUIRE_VECTOR(ctx);
   3439 
   3440     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3441                    avr_full_offset(a->vrb), 16, 16, &op[sign][vece]);
   3442 
   3443 
   3444     return true;
   3445 }
   3446 
   3447 
   3448 TRANS_FLAGS(ALTIVEC, VAVGSB, do_vx_vavg, 1, MO_8)
   3449 TRANS_FLAGS(ALTIVEC, VAVGSH, do_vx_vavg, 1, MO_16)
   3450 TRANS_FLAGS(ALTIVEC, VAVGSW, do_vx_vavg, 1, MO_32)
   3451 TRANS_FLAGS(ALTIVEC, VAVGUB, do_vx_vavg, 0, MO_8)
   3452 TRANS_FLAGS(ALTIVEC, VAVGUH, do_vx_vavg, 0, MO_16)
   3453 TRANS_FLAGS(ALTIVEC, VAVGUW, do_vx_vavg, 0, MO_32)
   3454 
   3455 static void gen_vabsdu(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
   3456 {
   3457     tcg_gen_umax_vec(vece, t, a, b);
   3458     tcg_gen_umin_vec(vece, a, a, b);
   3459     tcg_gen_sub_vec(vece, t, t, a);
   3460 }
   3461 
   3462 static bool do_vabsdu(DisasContext *ctx, arg_VX *a, const int vece)
   3463 {
   3464     static const TCGOpcode vecop_list[] = {
   3465         INDEX_op_umax_vec, INDEX_op_umin_vec, INDEX_op_sub_vec, 0
   3466     };
   3467 
   3468     static const GVecGen3 op[] = {
   3469         {
   3470             .fniv = gen_vabsdu,
   3471             .fno = gen_helper_VABSDUB,
   3472             .opt_opc = vecop_list,
   3473             .vece = MO_8
   3474         },
   3475         {
   3476             .fniv = gen_vabsdu,
   3477             .fno = gen_helper_VABSDUH,
   3478             .opt_opc = vecop_list,
   3479             .vece = MO_16
   3480         },
   3481         {
   3482             .fniv = gen_vabsdu,
   3483             .fno = gen_helper_VABSDUW,
   3484             .opt_opc = vecop_list,
   3485             .vece = MO_32
   3486         },
   3487     };
   3488 
   3489     REQUIRE_VECTOR(ctx);
   3490 
   3491     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3492                    avr_full_offset(a->vrb), 16, 16, &op[vece]);
   3493 
   3494     return true;
   3495 }
   3496 
   3497 TRANS_FLAGS2(ISA300, VABSDUB, do_vabsdu, MO_8)
   3498 TRANS_FLAGS2(ISA300, VABSDUH, do_vabsdu, MO_16)
   3499 TRANS_FLAGS2(ISA300, VABSDUW, do_vabsdu, MO_32)
   3500 
   3501 static bool do_vdiv_vmod(DisasContext *ctx, arg_VX *a, const int vece,
   3502                          void (*func_32)(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b),
   3503                          void (*func_64)(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b))
   3504 {
   3505     const GVecGen3 op = {
   3506         .fni4 = func_32,
   3507         .fni8 = func_64,
   3508         .vece = vece
   3509     };
   3510 
   3511     REQUIRE_VECTOR(ctx);
   3512 
   3513     tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
   3514                    avr_full_offset(a->vrb), 16, 16, &op);
   3515 
   3516     return true;
   3517 }
   3518 
   3519 #define DIVU32(NAME, DIV)                                               \
   3520 static void NAME(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)                    \
   3521 {                                                                       \
   3522     TCGv_i32 zero = tcg_constant_i32(0);                                \
   3523     TCGv_i32 one = tcg_constant_i32(1);                                 \
   3524     tcg_gen_movcond_i32(TCG_COND_EQ, b, b, zero, one, b);               \
   3525     DIV(t, a, b);                                                       \
   3526 }
   3527 
   3528 #define DIVS32(NAME, DIV)                                               \
   3529 static void NAME(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)                    \
   3530 {                                                                       \
   3531     TCGv_i32 t0 = tcg_temp_new_i32();                                   \
   3532     TCGv_i32 t1 = tcg_temp_new_i32();                                   \
   3533     tcg_gen_setcondi_i32(TCG_COND_EQ, t0, a, INT32_MIN);                \
   3534     tcg_gen_setcondi_i32(TCG_COND_EQ, t1, b, -1);                       \
   3535     tcg_gen_and_i32(t0, t0, t1);                                        \
   3536     tcg_gen_setcondi_i32(TCG_COND_EQ, t1, b, 0);                        \
   3537     tcg_gen_or_i32(t0, t0, t1);                                         \
   3538     tcg_gen_movi_i32(t1, 0);                                            \
   3539     tcg_gen_movcond_i32(TCG_COND_NE, b, t0, t1, t0, b);                 \
   3540     DIV(t, a, b);                                                       \
   3541     tcg_temp_free_i32(t0);                                              \
   3542     tcg_temp_free_i32(t1);                                              \
   3543 }
   3544 
   3545 #define DIVU64(NAME, DIV)                                               \
   3546 static void NAME(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)                    \
   3547 {                                                                       \
   3548     TCGv_i64 zero = tcg_constant_i64(0);                                \
   3549     TCGv_i64 one = tcg_constant_i64(1);                                 \
   3550     tcg_gen_movcond_i64(TCG_COND_EQ, b, b, zero, one, b);               \
   3551     DIV(t, a, b);                                                       \
   3552 }
   3553 
   3554 #define DIVS64(NAME, DIV)                                               \
   3555 static void NAME(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)                    \
   3556 {                                                                       \
   3557     TCGv_i64 t0 = tcg_temp_new_i64();                                   \
   3558     TCGv_i64 t1 = tcg_temp_new_i64();                                   \
   3559     tcg_gen_setcondi_i64(TCG_COND_EQ, t0, a, INT64_MIN);                \
   3560     tcg_gen_setcondi_i64(TCG_COND_EQ, t1, b, -1);                       \
   3561     tcg_gen_and_i64(t0, t0, t1);                                        \
   3562     tcg_gen_setcondi_i64(TCG_COND_EQ, t1, b, 0);                        \
   3563     tcg_gen_or_i64(t0, t0, t1);                                         \
   3564     tcg_gen_movi_i64(t1, 0);                                            \
   3565     tcg_gen_movcond_i64(TCG_COND_NE, b, t0, t1, t0, b);                 \
   3566     DIV(t, a, b);                                                       \
   3567     tcg_temp_free_i64(t0);                                              \
   3568     tcg_temp_free_i64(t1);                                              \
   3569 }
   3570 
   3571 DIVS32(do_divsw, tcg_gen_div_i32)
   3572 DIVU32(do_divuw, tcg_gen_divu_i32)
   3573 DIVS64(do_divsd, tcg_gen_div_i64)
   3574 DIVU64(do_divud, tcg_gen_divu_i64)
   3575 
   3576 TRANS_FLAGS2(ISA310, VDIVSW, do_vdiv_vmod, MO_32, do_divsw, NULL)
   3577 TRANS_FLAGS2(ISA310, VDIVUW, do_vdiv_vmod, MO_32, do_divuw, NULL)
   3578 TRANS_FLAGS2(ISA310, VDIVSD, do_vdiv_vmod, MO_64, NULL, do_divsd)
   3579 TRANS_FLAGS2(ISA310, VDIVUD, do_vdiv_vmod, MO_64, NULL, do_divud)
   3580 TRANS_FLAGS2(ISA310, VDIVSQ, do_vx_helper, gen_helper_VDIVSQ)
   3581 TRANS_FLAGS2(ISA310, VDIVUQ, do_vx_helper, gen_helper_VDIVUQ)
   3582 
   3583 static void do_dives_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
   3584 {
   3585     TCGv_i64 val1, val2;
   3586 
   3587     val1 = tcg_temp_new_i64();
   3588     val2 = tcg_temp_new_i64();
   3589 
   3590     tcg_gen_ext_i32_i64(val1, a);
   3591     tcg_gen_ext_i32_i64(val2, b);
   3592 
   3593     /* (a << 32)/b */
   3594     tcg_gen_shli_i64(val1, val1, 32);
   3595     tcg_gen_div_i64(val1, val1, val2);
   3596 
   3597     /* if quotient doesn't fit in 32 bits the result is undefined */
   3598     tcg_gen_extrl_i64_i32(t, val1);
   3599 
   3600     tcg_temp_free_i64(val1);
   3601     tcg_temp_free_i64(val2);
   3602 }
   3603 
   3604 static void do_diveu_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
   3605 {
   3606     TCGv_i64 val1, val2;
   3607 
   3608     val1 = tcg_temp_new_i64();
   3609     val2 = tcg_temp_new_i64();
   3610 
   3611     tcg_gen_extu_i32_i64(val1, a);
   3612     tcg_gen_extu_i32_i64(val2, b);
   3613 
   3614     /* (a << 32)/b */
   3615     tcg_gen_shli_i64(val1, val1, 32);
   3616     tcg_gen_divu_i64(val1, val1, val2);
   3617 
   3618     /* if quotient doesn't fit in 32 bits the result is undefined */
   3619     tcg_gen_extrl_i64_i32(t, val1);
   3620 
   3621     tcg_temp_free_i64(val1);
   3622     tcg_temp_free_i64(val2);
   3623 }
   3624 
   3625 DIVS32(do_divesw, do_dives_i32)
   3626 DIVU32(do_diveuw, do_diveu_i32)
   3627 
   3628 DIVS32(do_modsw, tcg_gen_rem_i32)
   3629 DIVU32(do_moduw, tcg_gen_remu_i32)
   3630 DIVS64(do_modsd, tcg_gen_rem_i64)
   3631 DIVU64(do_modud, tcg_gen_remu_i64)
   3632 
   3633 TRANS_FLAGS2(ISA310, VDIVESW, do_vdiv_vmod, MO_32, do_divesw, NULL)
   3634 TRANS_FLAGS2(ISA310, VDIVEUW, do_vdiv_vmod, MO_32, do_diveuw, NULL)
   3635 TRANS_FLAGS2(ISA310, VDIVESD, do_vx_helper, gen_helper_VDIVESD)
   3636 TRANS_FLAGS2(ISA310, VDIVEUD, do_vx_helper, gen_helper_VDIVEUD)
   3637 TRANS_FLAGS2(ISA310, VDIVESQ, do_vx_helper, gen_helper_VDIVESQ)
   3638 TRANS_FLAGS2(ISA310, VDIVEUQ, do_vx_helper, gen_helper_VDIVEUQ)
   3639 
   3640 TRANS_FLAGS2(ISA310, VMODSW, do_vdiv_vmod, MO_32, do_modsw , NULL)
   3641 TRANS_FLAGS2(ISA310, VMODUW, do_vdiv_vmod, MO_32, do_moduw, NULL)
   3642 TRANS_FLAGS2(ISA310, VMODSD, do_vdiv_vmod, MO_64, NULL, do_modsd)
   3643 TRANS_FLAGS2(ISA310, VMODUD, do_vdiv_vmod, MO_64, NULL, do_modud)
   3644 TRANS_FLAGS2(ISA310, VMODSQ, do_vx_helper, gen_helper_VMODSQ)
   3645 TRANS_FLAGS2(ISA310, VMODUQ, do_vx_helper, gen_helper_VMODUQ)
   3646 
   3647 #undef DIVS32
   3648 #undef DIVU32
   3649 #undef DIVS64
   3650 #undef DIVU64
   3651 
   3652 #undef GEN_VR_LDX
   3653 #undef GEN_VR_STX
   3654 #undef GEN_VR_LVE
   3655 #undef GEN_VR_STVE
   3656 
   3657 #undef GEN_VX_LOGICAL
   3658 #undef GEN_VX_LOGICAL_207
   3659 #undef GEN_VXFORM
   3660 #undef GEN_VXFORM_207
   3661 #undef GEN_VXFORM_DUAL
   3662 #undef GEN_VXRFORM_DUAL
   3663 #undef GEN_VXRFORM1
   3664 #undef GEN_VXRFORM
   3665 #undef GEN_VXFORM_VSPLTI
   3666 #undef GEN_VXFORM_NOA
   3667 #undef GEN_VXFORM_UIMM
   3668 #undef GEN_VAFORM_PAIRED
   3669 
   3670 #undef GEN_BCD2