qemu

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

vsx-impl.c.inc (109798B)


      1 /***                           VSX extension                               ***/
      2 
      3 static inline void get_cpu_vsr(TCGv_i64 dst, int n, bool high)
      4 {
      5     tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, high));
      6 }
      7 
      8 static inline void set_cpu_vsr(int n, TCGv_i64 src, bool high)
      9 {
     10     tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, high));
     11 }
     12 
     13 static inline TCGv_ptr gen_vsr_ptr(int reg)
     14 {
     15     TCGv_ptr r = tcg_temp_new_ptr();
     16     tcg_gen_addi_ptr(r, cpu_env, vsr_full_offset(reg));
     17     return r;
     18 }
     19 
     20 static inline TCGv_ptr gen_acc_ptr(int reg)
     21 {
     22     TCGv_ptr r = tcg_temp_new_ptr();
     23     tcg_gen_addi_ptr(r, cpu_env, acc_full_offset(reg));
     24     return r;
     25 }
     26 
     27 #define VSX_LOAD_SCALAR(name, operation)                      \
     28 static void gen_##name(DisasContext *ctx)                     \
     29 {                                                             \
     30     TCGv EA;                                                  \
     31     TCGv_i64 t0;                                              \
     32     if (unlikely(!ctx->vsx_enabled)) {                        \
     33         gen_exception(ctx, POWERPC_EXCP_VSXU);                \
     34         return;                                               \
     35     }                                                         \
     36     t0 = tcg_temp_new_i64();                                  \
     37     gen_set_access_type(ctx, ACCESS_INT);                     \
     38     EA = tcg_temp_new();                                      \
     39     gen_addr_reg_index(ctx, EA);                              \
     40     gen_qemu_##operation(ctx, t0, EA);                        \
     41     set_cpu_vsr(xT(ctx->opcode), t0, true);                   \
     42     /* NOTE: cpu_vsrl is undefined */                         \
     43     tcg_temp_free(EA);                                        \
     44     tcg_temp_free_i64(t0);                                    \
     45 }
     46 
     47 VSX_LOAD_SCALAR(lxsdx, ld64_i64)
     48 VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
     49 VSX_LOAD_SCALAR(lxsibzx, ld8u_i64)
     50 VSX_LOAD_SCALAR(lxsihzx, ld16u_i64)
     51 VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
     52 VSX_LOAD_SCALAR(lxsspx, ld32fs)
     53 
     54 static void gen_lxvd2x(DisasContext *ctx)
     55 {
     56     TCGv EA;
     57     TCGv_i64 t0;
     58     if (unlikely(!ctx->vsx_enabled)) {
     59         gen_exception(ctx, POWERPC_EXCP_VSXU);
     60         return;
     61     }
     62     t0 = tcg_temp_new_i64();
     63     gen_set_access_type(ctx, ACCESS_INT);
     64     EA = tcg_temp_new();
     65     gen_addr_reg_index(ctx, EA);
     66     gen_qemu_ld64_i64(ctx, t0, EA);
     67     set_cpu_vsr(xT(ctx->opcode), t0, true);
     68     tcg_gen_addi_tl(EA, EA, 8);
     69     gen_qemu_ld64_i64(ctx, t0, EA);
     70     set_cpu_vsr(xT(ctx->opcode), t0, false);
     71     tcg_temp_free(EA);
     72     tcg_temp_free_i64(t0);
     73 }
     74 
     75 static void gen_lxvw4x(DisasContext *ctx)
     76 {
     77     TCGv EA;
     78     TCGv_i64 xth;
     79     TCGv_i64 xtl;
     80     if (unlikely(!ctx->vsx_enabled)) {
     81         gen_exception(ctx, POWERPC_EXCP_VSXU);
     82         return;
     83     }
     84     xth = tcg_temp_new_i64();
     85     xtl = tcg_temp_new_i64();
     86 
     87     gen_set_access_type(ctx, ACCESS_INT);
     88     EA = tcg_temp_new();
     89 
     90     gen_addr_reg_index(ctx, EA);
     91     if (ctx->le_mode) {
     92         TCGv_i64 t0 = tcg_temp_new_i64();
     93         TCGv_i64 t1 = tcg_temp_new_i64();
     94 
     95         tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
     96         tcg_gen_shri_i64(t1, t0, 32);
     97         tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
     98         tcg_gen_addi_tl(EA, EA, 8);
     99         tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
    100         tcg_gen_shri_i64(t1, t0, 32);
    101         tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
    102         tcg_temp_free_i64(t0);
    103         tcg_temp_free_i64(t1);
    104     } else {
    105         tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
    106         tcg_gen_addi_tl(EA, EA, 8);
    107         tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
    108     }
    109     set_cpu_vsr(xT(ctx->opcode), xth, true);
    110     set_cpu_vsr(xT(ctx->opcode), xtl, false);
    111     tcg_temp_free(EA);
    112     tcg_temp_free_i64(xth);
    113     tcg_temp_free_i64(xtl);
    114 }
    115 
    116 static void gen_lxvwsx(DisasContext *ctx)
    117 {
    118     TCGv EA;
    119     TCGv_i32 data;
    120 
    121     if (xT(ctx->opcode) < 32) {
    122         if (unlikely(!ctx->vsx_enabled)) {
    123             gen_exception(ctx, POWERPC_EXCP_VSXU);
    124             return;
    125         }
    126     } else {
    127         if (unlikely(!ctx->altivec_enabled)) {
    128             gen_exception(ctx, POWERPC_EXCP_VPU);
    129             return;
    130         }
    131     }
    132 
    133     gen_set_access_type(ctx, ACCESS_INT);
    134     EA = tcg_temp_new();
    135 
    136     gen_addr_reg_index(ctx, EA);
    137 
    138     data = tcg_temp_new_i32();
    139     tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
    140     tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
    141 
    142     tcg_temp_free(EA);
    143     tcg_temp_free_i32(data);
    144 }
    145 
    146 static void gen_lxvdsx(DisasContext *ctx)
    147 {
    148     TCGv EA;
    149     TCGv_i64 data;
    150 
    151     if (unlikely(!ctx->vsx_enabled)) {
    152         gen_exception(ctx, POWERPC_EXCP_VSXU);
    153         return;
    154     }
    155 
    156     gen_set_access_type(ctx, ACCESS_INT);
    157     EA = tcg_temp_new();
    158 
    159     gen_addr_reg_index(ctx, EA);
    160 
    161     data = tcg_temp_new_i64();
    162     tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ));
    163     tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
    164 
    165     tcg_temp_free(EA);
    166     tcg_temp_free_i64(data);
    167 }
    168 
    169 static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
    170                           TCGv_i64 inh, TCGv_i64 inl)
    171 {
    172     TCGv_i64 mask = tcg_const_i64(0x00FF00FF00FF00FF);
    173     TCGv_i64 t0 = tcg_temp_new_i64();
    174     TCGv_i64 t1 = tcg_temp_new_i64();
    175 
    176     /* outh = ((inh & mask) << 8) | ((inh >> 8) & mask) */
    177     tcg_gen_and_i64(t0, inh, mask);
    178     tcg_gen_shli_i64(t0, t0, 8);
    179     tcg_gen_shri_i64(t1, inh, 8);
    180     tcg_gen_and_i64(t1, t1, mask);
    181     tcg_gen_or_i64(outh, t0, t1);
    182 
    183     /* outl = ((inl & mask) << 8) | ((inl >> 8) & mask) */
    184     tcg_gen_and_i64(t0, inl, mask);
    185     tcg_gen_shli_i64(t0, t0, 8);
    186     tcg_gen_shri_i64(t1, inl, 8);
    187     tcg_gen_and_i64(t1, t1, mask);
    188     tcg_gen_or_i64(outl, t0, t1);
    189 
    190     tcg_temp_free_i64(t0);
    191     tcg_temp_free_i64(t1);
    192     tcg_temp_free_i64(mask);
    193 }
    194 
    195 static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
    196                           TCGv_i64 inh, TCGv_i64 inl)
    197 {
    198     TCGv_i64 hi = tcg_temp_new_i64();
    199     TCGv_i64 lo = tcg_temp_new_i64();
    200 
    201     tcg_gen_bswap64_i64(hi, inh);
    202     tcg_gen_bswap64_i64(lo, inl);
    203     tcg_gen_shri_i64(outh, hi, 32);
    204     tcg_gen_deposit_i64(outh, outh, hi, 32, 32);
    205     tcg_gen_shri_i64(outl, lo, 32);
    206     tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
    207 
    208     tcg_temp_free_i64(hi);
    209     tcg_temp_free_i64(lo);
    210 }
    211 static void gen_lxvh8x(DisasContext *ctx)
    212 {
    213     TCGv EA;
    214     TCGv_i64 xth;
    215     TCGv_i64 xtl;
    216 
    217     if (unlikely(!ctx->vsx_enabled)) {
    218         gen_exception(ctx, POWERPC_EXCP_VSXU);
    219         return;
    220     }
    221     xth = tcg_temp_new_i64();
    222     xtl = tcg_temp_new_i64();
    223     gen_set_access_type(ctx, ACCESS_INT);
    224 
    225     EA = tcg_temp_new();
    226     gen_addr_reg_index(ctx, EA);
    227     tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
    228     tcg_gen_addi_tl(EA, EA, 8);
    229     tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
    230     if (ctx->le_mode) {
    231         gen_bswap16x8(xth, xtl, xth, xtl);
    232     }
    233     set_cpu_vsr(xT(ctx->opcode), xth, true);
    234     set_cpu_vsr(xT(ctx->opcode), xtl, false);
    235     tcg_temp_free(EA);
    236     tcg_temp_free_i64(xth);
    237     tcg_temp_free_i64(xtl);
    238 }
    239 
    240 static void gen_lxvb16x(DisasContext *ctx)
    241 {
    242     TCGv EA;
    243     TCGv_i64 xth;
    244     TCGv_i64 xtl;
    245 
    246     if (unlikely(!ctx->vsx_enabled)) {
    247         gen_exception(ctx, POWERPC_EXCP_VSXU);
    248         return;
    249     }
    250     xth = tcg_temp_new_i64();
    251     xtl = tcg_temp_new_i64();
    252     gen_set_access_type(ctx, ACCESS_INT);
    253     EA = tcg_temp_new();
    254     gen_addr_reg_index(ctx, EA);
    255     tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
    256     tcg_gen_addi_tl(EA, EA, 8);
    257     tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
    258     set_cpu_vsr(xT(ctx->opcode), xth, true);
    259     set_cpu_vsr(xT(ctx->opcode), xtl, false);
    260     tcg_temp_free(EA);
    261     tcg_temp_free_i64(xth);
    262     tcg_temp_free_i64(xtl);
    263 }
    264 
    265 #ifdef TARGET_PPC64
    266 #define VSX_VECTOR_LOAD_STORE_LENGTH(name)                         \
    267 static void gen_##name(DisasContext *ctx)                          \
    268 {                                                                  \
    269     TCGv EA;                                                       \
    270     TCGv_ptr xt;                                                   \
    271                                                                    \
    272     if (xT(ctx->opcode) < 32) {                                    \
    273         if (unlikely(!ctx->vsx_enabled)) {                         \
    274             gen_exception(ctx, POWERPC_EXCP_VSXU);                 \
    275             return;                                                \
    276         }                                                          \
    277     } else {                                                       \
    278         if (unlikely(!ctx->altivec_enabled)) {                     \
    279             gen_exception(ctx, POWERPC_EXCP_VPU);                  \
    280             return;                                                \
    281         }                                                          \
    282     }                                                              \
    283     EA = tcg_temp_new();                                           \
    284     xt = gen_vsr_ptr(xT(ctx->opcode));                             \
    285     gen_set_access_type(ctx, ACCESS_INT);                          \
    286     gen_addr_register(ctx, EA);                                    \
    287     gen_helper_##name(cpu_env, EA, xt, cpu_gpr[rB(ctx->opcode)]);  \
    288     tcg_temp_free(EA);                                             \
    289     tcg_temp_free_ptr(xt);                                         \
    290 }
    291 
    292 VSX_VECTOR_LOAD_STORE_LENGTH(lxvl)
    293 VSX_VECTOR_LOAD_STORE_LENGTH(lxvll)
    294 VSX_VECTOR_LOAD_STORE_LENGTH(stxvl)
    295 VSX_VECTOR_LOAD_STORE_LENGTH(stxvll)
    296 #endif
    297 
    298 #define VSX_STORE_SCALAR(name, operation)                     \
    299 static void gen_##name(DisasContext *ctx)                     \
    300 {                                                             \
    301     TCGv EA;                                                  \
    302     TCGv_i64 t0;                                              \
    303     if (unlikely(!ctx->vsx_enabled)) {                        \
    304         gen_exception(ctx, POWERPC_EXCP_VSXU);                \
    305         return;                                               \
    306     }                                                         \
    307     t0 = tcg_temp_new_i64();                                  \
    308     gen_set_access_type(ctx, ACCESS_INT);                     \
    309     EA = tcg_temp_new();                                      \
    310     gen_addr_reg_index(ctx, EA);                              \
    311     get_cpu_vsr(t0, xS(ctx->opcode), true);                   \
    312     gen_qemu_##operation(ctx, t0, EA);                        \
    313     tcg_temp_free(EA);                                        \
    314     tcg_temp_free_i64(t0);                                    \
    315 }
    316 
    317 VSX_STORE_SCALAR(stxsdx, st64_i64)
    318 
    319 VSX_STORE_SCALAR(stxsibx, st8_i64)
    320 VSX_STORE_SCALAR(stxsihx, st16_i64)
    321 VSX_STORE_SCALAR(stxsiwx, st32_i64)
    322 VSX_STORE_SCALAR(stxsspx, st32fs)
    323 
    324 static void gen_stxvd2x(DisasContext *ctx)
    325 {
    326     TCGv EA;
    327     TCGv_i64 t0;
    328     if (unlikely(!ctx->vsx_enabled)) {
    329         gen_exception(ctx, POWERPC_EXCP_VSXU);
    330         return;
    331     }
    332     t0 = tcg_temp_new_i64();
    333     gen_set_access_type(ctx, ACCESS_INT);
    334     EA = tcg_temp_new();
    335     gen_addr_reg_index(ctx, EA);
    336     get_cpu_vsr(t0, xS(ctx->opcode), true);
    337     gen_qemu_st64_i64(ctx, t0, EA);
    338     tcg_gen_addi_tl(EA, EA, 8);
    339     get_cpu_vsr(t0, xS(ctx->opcode), false);
    340     gen_qemu_st64_i64(ctx, t0, EA);
    341     tcg_temp_free(EA);
    342     tcg_temp_free_i64(t0);
    343 }
    344 
    345 static void gen_stxvw4x(DisasContext *ctx)
    346 {
    347     TCGv EA;
    348     TCGv_i64 xsh;
    349     TCGv_i64 xsl;
    350 
    351     if (unlikely(!ctx->vsx_enabled)) {
    352         gen_exception(ctx, POWERPC_EXCP_VSXU);
    353         return;
    354     }
    355     xsh = tcg_temp_new_i64();
    356     xsl = tcg_temp_new_i64();
    357     get_cpu_vsr(xsh, xS(ctx->opcode), true);
    358     get_cpu_vsr(xsl, xS(ctx->opcode), false);
    359     gen_set_access_type(ctx, ACCESS_INT);
    360     EA = tcg_temp_new();
    361     gen_addr_reg_index(ctx, EA);
    362     if (ctx->le_mode) {
    363         TCGv_i64 t0 = tcg_temp_new_i64();
    364         TCGv_i64 t1 = tcg_temp_new_i64();
    365 
    366         tcg_gen_shri_i64(t0, xsh, 32);
    367         tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
    368         tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
    369         tcg_gen_addi_tl(EA, EA, 8);
    370         tcg_gen_shri_i64(t0, xsl, 32);
    371         tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
    372         tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
    373         tcg_temp_free_i64(t0);
    374         tcg_temp_free_i64(t1);
    375     } else {
    376         tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
    377         tcg_gen_addi_tl(EA, EA, 8);
    378         tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
    379     }
    380     tcg_temp_free(EA);
    381     tcg_temp_free_i64(xsh);
    382     tcg_temp_free_i64(xsl);
    383 }
    384 
    385 static void gen_stxvh8x(DisasContext *ctx)
    386 {
    387     TCGv EA;
    388     TCGv_i64 xsh;
    389     TCGv_i64 xsl;
    390 
    391     if (unlikely(!ctx->vsx_enabled)) {
    392         gen_exception(ctx, POWERPC_EXCP_VSXU);
    393         return;
    394     }
    395     xsh = tcg_temp_new_i64();
    396     xsl = tcg_temp_new_i64();
    397     get_cpu_vsr(xsh, xS(ctx->opcode), true);
    398     get_cpu_vsr(xsl, xS(ctx->opcode), false);
    399     gen_set_access_type(ctx, ACCESS_INT);
    400     EA = tcg_temp_new();
    401     gen_addr_reg_index(ctx, EA);
    402     if (ctx->le_mode) {
    403         TCGv_i64 outh = tcg_temp_new_i64();
    404         TCGv_i64 outl = tcg_temp_new_i64();
    405 
    406         gen_bswap16x8(outh, outl, xsh, xsl);
    407         tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEUQ);
    408         tcg_gen_addi_tl(EA, EA, 8);
    409         tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEUQ);
    410         tcg_temp_free_i64(outh);
    411         tcg_temp_free_i64(outl);
    412     } else {
    413         tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
    414         tcg_gen_addi_tl(EA, EA, 8);
    415         tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
    416     }
    417     tcg_temp_free(EA);
    418     tcg_temp_free_i64(xsh);
    419     tcg_temp_free_i64(xsl);
    420 }
    421 
    422 static void gen_stxvb16x(DisasContext *ctx)
    423 {
    424     TCGv EA;
    425     TCGv_i64 xsh;
    426     TCGv_i64 xsl;
    427 
    428     if (unlikely(!ctx->vsx_enabled)) {
    429         gen_exception(ctx, POWERPC_EXCP_VSXU);
    430         return;
    431     }
    432     xsh = tcg_temp_new_i64();
    433     xsl = tcg_temp_new_i64();
    434     get_cpu_vsr(xsh, xS(ctx->opcode), true);
    435     get_cpu_vsr(xsl, xS(ctx->opcode), false);
    436     gen_set_access_type(ctx, ACCESS_INT);
    437     EA = tcg_temp_new();
    438     gen_addr_reg_index(ctx, EA);
    439     tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
    440     tcg_gen_addi_tl(EA, EA, 8);
    441     tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
    442     tcg_temp_free(EA);
    443     tcg_temp_free_i64(xsh);
    444     tcg_temp_free_i64(xsl);
    445 }
    446 
    447 static void gen_mfvsrwz(DisasContext *ctx)
    448 {
    449     if (xS(ctx->opcode) < 32) {
    450         if (unlikely(!ctx->fpu_enabled)) {
    451             gen_exception(ctx, POWERPC_EXCP_FPU);
    452             return;
    453         }
    454     } else {
    455         if (unlikely(!ctx->altivec_enabled)) {
    456             gen_exception(ctx, POWERPC_EXCP_VPU);
    457             return;
    458         }
    459     }
    460     TCGv_i64 tmp = tcg_temp_new_i64();
    461     TCGv_i64 xsh = tcg_temp_new_i64();
    462     get_cpu_vsr(xsh, xS(ctx->opcode), true);
    463     tcg_gen_ext32u_i64(tmp, xsh);
    464     tcg_gen_trunc_i64_tl(cpu_gpr[rA(ctx->opcode)], tmp);
    465     tcg_temp_free_i64(tmp);
    466     tcg_temp_free_i64(xsh);
    467 }
    468 
    469 static void gen_mtvsrwa(DisasContext *ctx)
    470 {
    471     if (xS(ctx->opcode) < 32) {
    472         if (unlikely(!ctx->fpu_enabled)) {
    473             gen_exception(ctx, POWERPC_EXCP_FPU);
    474             return;
    475         }
    476     } else {
    477         if (unlikely(!ctx->altivec_enabled)) {
    478             gen_exception(ctx, POWERPC_EXCP_VPU);
    479             return;
    480         }
    481     }
    482     TCGv_i64 tmp = tcg_temp_new_i64();
    483     TCGv_i64 xsh = tcg_temp_new_i64();
    484     tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
    485     tcg_gen_ext32s_i64(xsh, tmp);
    486     set_cpu_vsr(xT(ctx->opcode), xsh, true);
    487     tcg_temp_free_i64(tmp);
    488     tcg_temp_free_i64(xsh);
    489 }
    490 
    491 static void gen_mtvsrwz(DisasContext *ctx)
    492 {
    493     if (xS(ctx->opcode) < 32) {
    494         if (unlikely(!ctx->fpu_enabled)) {
    495             gen_exception(ctx, POWERPC_EXCP_FPU);
    496             return;
    497         }
    498     } else {
    499         if (unlikely(!ctx->altivec_enabled)) {
    500             gen_exception(ctx, POWERPC_EXCP_VPU);
    501             return;
    502         }
    503     }
    504     TCGv_i64 tmp = tcg_temp_new_i64();
    505     TCGv_i64 xsh = tcg_temp_new_i64();
    506     tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
    507     tcg_gen_ext32u_i64(xsh, tmp);
    508     set_cpu_vsr(xT(ctx->opcode), xsh, true);
    509     tcg_temp_free_i64(tmp);
    510     tcg_temp_free_i64(xsh);
    511 }
    512 
    513 #if defined(TARGET_PPC64)
    514 static void gen_mfvsrd(DisasContext *ctx)
    515 {
    516     TCGv_i64 t0;
    517     if (xS(ctx->opcode) < 32) {
    518         if (unlikely(!ctx->fpu_enabled)) {
    519             gen_exception(ctx, POWERPC_EXCP_FPU);
    520             return;
    521         }
    522     } else {
    523         if (unlikely(!ctx->altivec_enabled)) {
    524             gen_exception(ctx, POWERPC_EXCP_VPU);
    525             return;
    526         }
    527     }
    528     t0 = tcg_temp_new_i64();
    529     get_cpu_vsr(t0, xS(ctx->opcode), true);
    530     tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
    531     tcg_temp_free_i64(t0);
    532 }
    533 
    534 static void gen_mtvsrd(DisasContext *ctx)
    535 {
    536     TCGv_i64 t0;
    537     if (xS(ctx->opcode) < 32) {
    538         if (unlikely(!ctx->fpu_enabled)) {
    539             gen_exception(ctx, POWERPC_EXCP_FPU);
    540             return;
    541         }
    542     } else {
    543         if (unlikely(!ctx->altivec_enabled)) {
    544             gen_exception(ctx, POWERPC_EXCP_VPU);
    545             return;
    546         }
    547     }
    548     t0 = tcg_temp_new_i64();
    549     tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    550     set_cpu_vsr(xT(ctx->opcode), t0, true);
    551     tcg_temp_free_i64(t0);
    552 }
    553 
    554 static void gen_mfvsrld(DisasContext *ctx)
    555 {
    556     TCGv_i64 t0;
    557     if (xS(ctx->opcode) < 32) {
    558         if (unlikely(!ctx->vsx_enabled)) {
    559             gen_exception(ctx, POWERPC_EXCP_VSXU);
    560             return;
    561         }
    562     } else {
    563         if (unlikely(!ctx->altivec_enabled)) {
    564             gen_exception(ctx, POWERPC_EXCP_VPU);
    565             return;
    566         }
    567     }
    568     t0 = tcg_temp_new_i64();
    569     get_cpu_vsr(t0, xS(ctx->opcode), false);
    570     tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
    571     tcg_temp_free_i64(t0);
    572 }
    573 
    574 static void gen_mtvsrdd(DisasContext *ctx)
    575 {
    576     TCGv_i64 t0;
    577     if (xT(ctx->opcode) < 32) {
    578         if (unlikely(!ctx->vsx_enabled)) {
    579             gen_exception(ctx, POWERPC_EXCP_VSXU);
    580             return;
    581         }
    582     } else {
    583         if (unlikely(!ctx->altivec_enabled)) {
    584             gen_exception(ctx, POWERPC_EXCP_VPU);
    585             return;
    586         }
    587     }
    588 
    589     t0 = tcg_temp_new_i64();
    590     if (!rA(ctx->opcode)) {
    591         tcg_gen_movi_i64(t0, 0);
    592     } else {
    593         tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
    594     }
    595     set_cpu_vsr(xT(ctx->opcode), t0, true);
    596 
    597     tcg_gen_mov_i64(t0, cpu_gpr[rB(ctx->opcode)]);
    598     set_cpu_vsr(xT(ctx->opcode), t0, false);
    599     tcg_temp_free_i64(t0);
    600 }
    601 
    602 static void gen_mtvsrws(DisasContext *ctx)
    603 {
    604     TCGv_i64 t0;
    605     if (xT(ctx->opcode) < 32) {
    606         if (unlikely(!ctx->vsx_enabled)) {
    607             gen_exception(ctx, POWERPC_EXCP_VSXU);
    608             return;
    609         }
    610     } else {
    611         if (unlikely(!ctx->altivec_enabled)) {
    612             gen_exception(ctx, POWERPC_EXCP_VPU);
    613             return;
    614         }
    615     }
    616 
    617     t0 = tcg_temp_new_i64();
    618     tcg_gen_deposit_i64(t0, cpu_gpr[rA(ctx->opcode)],
    619                         cpu_gpr[rA(ctx->opcode)], 32, 32);
    620     set_cpu_vsr(xT(ctx->opcode), t0, false);
    621     set_cpu_vsr(xT(ctx->opcode), t0, true);
    622     tcg_temp_free_i64(t0);
    623 }
    624 
    625 #endif
    626 
    627 #define OP_ABS 1
    628 #define OP_NABS 2
    629 #define OP_NEG 3
    630 #define OP_CPSGN 4
    631 #define SGN_MASK_DP  0x8000000000000000ull
    632 #define SGN_MASK_SP 0x8000000080000000ull
    633 #define EXP_MASK_DP  0x7FF0000000000000ull
    634 #define EXP_MASK_SP 0x7F8000007F800000ull
    635 #define FRC_MASK_DP (~(SGN_MASK_DP | EXP_MASK_DP))
    636 #define FRC_MASK_SP (~(SGN_MASK_SP | EXP_MASK_SP))
    637 
    638 #define VSX_SCALAR_MOVE(name, op, sgn_mask)                       \
    639 static void glue(gen_, name)(DisasContext *ctx)                   \
    640     {                                                             \
    641         TCGv_i64 xb, sgm;                                         \
    642         if (unlikely(!ctx->vsx_enabled)) {                        \
    643             gen_exception(ctx, POWERPC_EXCP_VSXU);                \
    644             return;                                               \
    645         }                                                         \
    646         xb = tcg_temp_new_i64();                                  \
    647         sgm = tcg_temp_new_i64();                                 \
    648         get_cpu_vsr(xb, xB(ctx->opcode), true);                   \
    649         tcg_gen_movi_i64(sgm, sgn_mask);                          \
    650         switch (op) {                                             \
    651             case OP_ABS: {                                        \
    652                 tcg_gen_andc_i64(xb, xb, sgm);                    \
    653                 break;                                            \
    654             }                                                     \
    655             case OP_NABS: {                                       \
    656                 tcg_gen_or_i64(xb, xb, sgm);                      \
    657                 break;                                            \
    658             }                                                     \
    659             case OP_NEG: {                                        \
    660                 tcg_gen_xor_i64(xb, xb, sgm);                     \
    661                 break;                                            \
    662             }                                                     \
    663             case OP_CPSGN: {                                      \
    664                 TCGv_i64 xa = tcg_temp_new_i64();                 \
    665                 get_cpu_vsr(xa, xA(ctx->opcode), true);           \
    666                 tcg_gen_and_i64(xa, xa, sgm);                     \
    667                 tcg_gen_andc_i64(xb, xb, sgm);                    \
    668                 tcg_gen_or_i64(xb, xb, xa);                       \
    669                 tcg_temp_free_i64(xa);                            \
    670                 break;                                            \
    671             }                                                     \
    672         }                                                         \
    673         set_cpu_vsr(xT(ctx->opcode), xb, true);                   \
    674         set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
    675         tcg_temp_free_i64(xb);                                    \
    676         tcg_temp_free_i64(sgm);                                   \
    677     }
    678 
    679 VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
    680 VSX_SCALAR_MOVE(xsnabsdp, OP_NABS, SGN_MASK_DP)
    681 VSX_SCALAR_MOVE(xsnegdp, OP_NEG, SGN_MASK_DP)
    682 VSX_SCALAR_MOVE(xscpsgndp, OP_CPSGN, SGN_MASK_DP)
    683 
    684 #define VSX_SCALAR_MOVE_QP(name, op, sgn_mask)                    \
    685 static void glue(gen_, name)(DisasContext *ctx)                   \
    686 {                                                                 \
    687     int xa;                                                       \
    688     int xt = rD(ctx->opcode) + 32;                                \
    689     int xb = rB(ctx->opcode) + 32;                                \
    690     TCGv_i64 xah, xbh, xbl, sgm, tmp;                             \
    691                                                                   \
    692     if (unlikely(!ctx->vsx_enabled)) {                            \
    693         gen_exception(ctx, POWERPC_EXCP_VSXU);                    \
    694         return;                                                   \
    695     }                                                             \
    696     xbh = tcg_temp_new_i64();                                     \
    697     xbl = tcg_temp_new_i64();                                     \
    698     sgm = tcg_temp_new_i64();                                     \
    699     tmp = tcg_temp_new_i64();                                     \
    700     get_cpu_vsr(xbh, xb, true);                                   \
    701     get_cpu_vsr(xbl, xb, false);                                  \
    702     tcg_gen_movi_i64(sgm, sgn_mask);                              \
    703     switch (op) {                                                 \
    704     case OP_ABS:                                                  \
    705         tcg_gen_andc_i64(xbh, xbh, sgm);                          \
    706         break;                                                    \
    707     case OP_NABS:                                                 \
    708         tcg_gen_or_i64(xbh, xbh, sgm);                            \
    709         break;                                                    \
    710     case OP_NEG:                                                  \
    711         tcg_gen_xor_i64(xbh, xbh, sgm);                           \
    712         break;                                                    \
    713     case OP_CPSGN:                                                \
    714         xah = tcg_temp_new_i64();                                 \
    715         xa = rA(ctx->opcode) + 32;                                \
    716         get_cpu_vsr(tmp, xa, true);                               \
    717         tcg_gen_and_i64(xah, tmp, sgm);                           \
    718         tcg_gen_andc_i64(xbh, xbh, sgm);                          \
    719         tcg_gen_or_i64(xbh, xbh, xah);                            \
    720         tcg_temp_free_i64(xah);                                   \
    721         break;                                                    \
    722     }                                                             \
    723     set_cpu_vsr(xt, xbh, true);                                   \
    724     set_cpu_vsr(xt, xbl, false);                                  \
    725     tcg_temp_free_i64(xbl);                                       \
    726     tcg_temp_free_i64(xbh);                                       \
    727     tcg_temp_free_i64(sgm);                                       \
    728     tcg_temp_free_i64(tmp);                                       \
    729 }
    730 
    731 VSX_SCALAR_MOVE_QP(xsabsqp, OP_ABS, SGN_MASK_DP)
    732 VSX_SCALAR_MOVE_QP(xsnabsqp, OP_NABS, SGN_MASK_DP)
    733 VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP)
    734 VSX_SCALAR_MOVE_QP(xscpsgnqp, OP_CPSGN, SGN_MASK_DP)
    735 
    736 #define TCG_OP_IMM_i64(FUNC, OP, IMM)                           \
    737     static void FUNC(TCGv_i64 t, TCGv_i64 b)                    \
    738     {                                                           \
    739         OP(t, b, IMM);                                          \
    740     }
    741 
    742 TCG_OP_IMM_i64(do_xvabssp_i64, tcg_gen_andi_i64, ~SGN_MASK_SP)
    743 TCG_OP_IMM_i64(do_xvnabssp_i64, tcg_gen_ori_i64, SGN_MASK_SP)
    744 TCG_OP_IMM_i64(do_xvnegsp_i64, tcg_gen_xori_i64, SGN_MASK_SP)
    745 TCG_OP_IMM_i64(do_xvabsdp_i64, tcg_gen_andi_i64, ~SGN_MASK_DP)
    746 TCG_OP_IMM_i64(do_xvnabsdp_i64, tcg_gen_ori_i64, SGN_MASK_DP)
    747 TCG_OP_IMM_i64(do_xvnegdp_i64, tcg_gen_xori_i64, SGN_MASK_DP)
    748 #undef TCG_OP_IMM_i64
    749 
    750 static void xv_msb_op1(unsigned vece, TCGv_vec t, TCGv_vec b,
    751                  void (*tcg_gen_op_vec)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
    752 {
    753     uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
    754     tcg_gen_op_vec(vece, t, b, tcg_constant_vec_matching(t, vece, msb));
    755 }
    756 
    757 static void do_xvabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
    758 {
    759     xv_msb_op1(vece, t, b, tcg_gen_andc_vec);
    760 }
    761 
    762 static void do_xvnabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
    763 {
    764     xv_msb_op1(vece, t, b, tcg_gen_or_vec);
    765 }
    766 
    767 static void do_xvneg_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
    768 {
    769     xv_msb_op1(vece, t, b, tcg_gen_xor_vec);
    770 }
    771 
    772 static bool do_vsx_msb_op(DisasContext *ctx, arg_XX2 *a, unsigned vece,
    773                           void (*vec)(unsigned, TCGv_vec, TCGv_vec),
    774                           void (*i64)(TCGv_i64, TCGv_i64))
    775 {
    776     static const TCGOpcode vecop_list[] = {
    777         0
    778     };
    779 
    780     const GVecGen2 op = {
    781        .fni8 = i64,
    782        .fniv = vec,
    783        .opt_opc = vecop_list,
    784        .vece = vece
    785     };
    786 
    787     REQUIRE_INSNS_FLAGS2(ctx, VSX);
    788     REQUIRE_VSX(ctx);
    789 
    790     tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
    791                    16, 16, &op);
    792 
    793     return true;
    794 }
    795 
    796 TRANS(XVABSDP, do_vsx_msb_op, MO_64, do_xvabs_vec, do_xvabsdp_i64)
    797 TRANS(XVNABSDP, do_vsx_msb_op, MO_64, do_xvnabs_vec, do_xvnabsdp_i64)
    798 TRANS(XVNEGDP, do_vsx_msb_op, MO_64, do_xvneg_vec, do_xvnegdp_i64)
    799 TRANS(XVABSSP, do_vsx_msb_op, MO_32, do_xvabs_vec, do_xvabssp_i64)
    800 TRANS(XVNABSSP, do_vsx_msb_op, MO_32, do_xvnabs_vec, do_xvnabssp_i64)
    801 TRANS(XVNEGSP, do_vsx_msb_op, MO_32, do_xvneg_vec, do_xvnegsp_i64)
    802 
    803 static void do_xvcpsgndp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
    804 {
    805     tcg_gen_andi_i64(a, a, SGN_MASK_DP);
    806     tcg_gen_andi_i64(b, b, ~SGN_MASK_DP);
    807     tcg_gen_or_i64(t, a, b);
    808 }
    809 
    810 static void do_xvcpsgnsp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
    811 {
    812     tcg_gen_andi_i64(a, a, SGN_MASK_SP);
    813     tcg_gen_andi_i64(b, b, ~SGN_MASK_SP);
    814     tcg_gen_or_i64(t, a, b);
    815 }
    816 
    817 static void do_xvcpsgn_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
    818 {
    819     uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
    820     tcg_gen_bitsel_vec(vece, t, tcg_constant_vec_matching(t, vece, msb), a, b);
    821 }
    822 
    823 static bool do_xvcpsgn(DisasContext *ctx, arg_XX3 *a, unsigned vece)
    824 {
    825     static const TCGOpcode vecop_list[] = {
    826         0
    827     };
    828 
    829     static const GVecGen3 op[] = {
    830         {
    831             .fni8 = do_xvcpsgnsp_i64,
    832             .fniv = do_xvcpsgn_vec,
    833             .opt_opc = vecop_list,
    834             .vece = MO_32
    835         },
    836         {
    837             .fni8 = do_xvcpsgndp_i64,
    838             .fniv = do_xvcpsgn_vec,
    839             .opt_opc = vecop_list,
    840             .vece = MO_64
    841         },
    842     };
    843 
    844     REQUIRE_INSNS_FLAGS2(ctx, VSX);
    845     REQUIRE_VSX(ctx);
    846 
    847     tcg_gen_gvec_3(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
    848                    vsr_full_offset(a->xb), 16, 16, &op[vece - MO_32]);
    849 
    850     return true;
    851 }
    852 
    853 TRANS(XVCPSGNSP, do_xvcpsgn, MO_32)
    854 TRANS(XVCPSGNDP, do_xvcpsgn, MO_64)
    855 
    856 #define VSX_CMP(name, op1, op2, inval, type)                                  \
    857 static void gen_##name(DisasContext *ctx)                                     \
    858 {                                                                             \
    859     TCGv_i32 ignored;                                                         \
    860     TCGv_ptr xt, xa, xb;                                                      \
    861     if (unlikely(!ctx->vsx_enabled)) {                                        \
    862         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
    863         return;                                                               \
    864     }                                                                         \
    865     xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
    866     xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
    867     xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
    868     if ((ctx->opcode >> (31 - 21)) & 1) {                                     \
    869         gen_helper_##name(cpu_crf[6], cpu_env, xt, xa, xb);                   \
    870     } else {                                                                  \
    871         ignored = tcg_temp_new_i32();                                         \
    872         gen_helper_##name(ignored, cpu_env, xt, xa, xb);                      \
    873         tcg_temp_free_i32(ignored);                                           \
    874     }                                                                         \
    875     tcg_temp_free_ptr(xt);                                                    \
    876     tcg_temp_free_ptr(xa);                                                    \
    877     tcg_temp_free_ptr(xb);                                                    \
    878 }
    879 
    880 VSX_CMP(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
    881 VSX_CMP(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
    882 VSX_CMP(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
    883 VSX_CMP(xvcmpnedp, 0x0C, 0x0F, 0, PPC2_ISA300)
    884 VSX_CMP(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
    885 VSX_CMP(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
    886 VSX_CMP(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
    887 VSX_CMP(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX)
    888 
    889 static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a)
    890 {
    891     TCGv_i32 ro;
    892     TCGv_ptr xt, xb;
    893 
    894     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
    895     REQUIRE_VSX(ctx);
    896 
    897     ro = tcg_const_i32(a->rc);
    898 
    899     xt = gen_avr_ptr(a->rt);
    900     xb = gen_avr_ptr(a->rb);
    901     gen_helper_XSCVQPDP(cpu_env, ro, xt, xb);
    902     tcg_temp_free_i32(ro);
    903     tcg_temp_free_ptr(xt);
    904     tcg_temp_free_ptr(xb);
    905 
    906     return true;
    907 }
    908 
    909 static bool do_helper_env_X_tb(DisasContext *ctx, arg_X_tb *a,
    910                                void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
    911 {
    912     TCGv_ptr xt, xb;
    913 
    914     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
    915     REQUIRE_VSX(ctx);
    916 
    917     xt = gen_avr_ptr(a->rt);
    918     xb = gen_avr_ptr(a->rb);
    919     gen_helper(cpu_env, xt, xb);
    920     tcg_temp_free_ptr(xt);
    921     tcg_temp_free_ptr(xb);
    922 
    923     return true;
    924 }
    925 
    926 TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP)
    927 TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP)
    928 TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ)
    929 TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ)
    930 
    931 #define GEN_VSX_HELPER_2(name, op1, op2, inval, type)                         \
    932 static void gen_##name(DisasContext *ctx)                                     \
    933 {                                                                             \
    934     TCGv_i32 opc;                                                             \
    935     if (unlikely(!ctx->vsx_enabled)) {                                        \
    936         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
    937         return;                                                               \
    938     }                                                                         \
    939     opc = tcg_const_i32(ctx->opcode);                                         \
    940     gen_helper_##name(cpu_env, opc);                                          \
    941     tcg_temp_free_i32(opc);                                                   \
    942 }
    943 
    944 #define GEN_VSX_HELPER_X3(name, op1, op2, inval, type)                        \
    945 static void gen_##name(DisasContext *ctx)                                     \
    946 {                                                                             \
    947     TCGv_ptr xt, xa, xb;                                                      \
    948     if (unlikely(!ctx->vsx_enabled)) {                                        \
    949         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
    950         return;                                                               \
    951     }                                                                         \
    952     xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
    953     xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
    954     xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
    955     gen_helper_##name(cpu_env, xt, xa, xb);                                   \
    956     tcg_temp_free_ptr(xt);                                                    \
    957     tcg_temp_free_ptr(xa);                                                    \
    958     tcg_temp_free_ptr(xb);                                                    \
    959 }
    960 
    961 #define GEN_VSX_HELPER_X2(name, op1, op2, inval, type)                        \
    962 static void gen_##name(DisasContext *ctx)                                     \
    963 {                                                                             \
    964     TCGv_ptr xt, xb;                                                          \
    965     if (unlikely(!ctx->vsx_enabled)) {                                        \
    966         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
    967         return;                                                               \
    968     }                                                                         \
    969     xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
    970     xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
    971     gen_helper_##name(cpu_env, xt, xb);                                       \
    972     tcg_temp_free_ptr(xt);                                                    \
    973     tcg_temp_free_ptr(xb);                                                    \
    974 }
    975 
    976 #define GEN_VSX_HELPER_X2_AB(name, op1, op2, inval, type)                     \
    977 static void gen_##name(DisasContext *ctx)                                     \
    978 {                                                                             \
    979     TCGv_i32 opc;                                                             \
    980     TCGv_ptr xa, xb;                                                          \
    981     if (unlikely(!ctx->vsx_enabled)) {                                        \
    982         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
    983         return;                                                               \
    984     }                                                                         \
    985     opc = tcg_const_i32(ctx->opcode);                                         \
    986     xa = gen_vsr_ptr(xA(ctx->opcode));                                        \
    987     xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
    988     gen_helper_##name(cpu_env, opc, xa, xb);                                  \
    989     tcg_temp_free_i32(opc);                                                   \
    990     tcg_temp_free_ptr(xa);                                                    \
    991     tcg_temp_free_ptr(xb);                                                    \
    992 }
    993 
    994 #define GEN_VSX_HELPER_X1(name, op1, op2, inval, type)                        \
    995 static void gen_##name(DisasContext *ctx)                                     \
    996 {                                                                             \
    997     TCGv_i32 opc;                                                             \
    998     TCGv_ptr xb;                                                              \
    999     if (unlikely(!ctx->vsx_enabled)) {                                        \
   1000         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
   1001         return;                                                               \
   1002     }                                                                         \
   1003     opc = tcg_const_i32(ctx->opcode);                                         \
   1004     xb = gen_vsr_ptr(xB(ctx->opcode));                                        \
   1005     gen_helper_##name(cpu_env, opc, xb);                                      \
   1006     tcg_temp_free_i32(opc);                                                   \
   1007     tcg_temp_free_ptr(xb);                                                    \
   1008 }
   1009 
   1010 #define GEN_VSX_HELPER_R3(name, op1, op2, inval, type)                        \
   1011 static void gen_##name(DisasContext *ctx)                                     \
   1012 {                                                                             \
   1013     TCGv_i32 opc;                                                             \
   1014     TCGv_ptr xt, xa, xb;                                                      \
   1015     if (unlikely(!ctx->vsx_enabled)) {                                        \
   1016         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
   1017         return;                                                               \
   1018     }                                                                         \
   1019     opc = tcg_const_i32(ctx->opcode);                                         \
   1020     xt = gen_vsr_ptr(rD(ctx->opcode) + 32);                                   \
   1021     xa = gen_vsr_ptr(rA(ctx->opcode) + 32);                                   \
   1022     xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
   1023     gen_helper_##name(cpu_env, opc, xt, xa, xb);                              \
   1024     tcg_temp_free_i32(opc);                                                   \
   1025     tcg_temp_free_ptr(xt);                                                    \
   1026     tcg_temp_free_ptr(xa);                                                    \
   1027     tcg_temp_free_ptr(xb);                                                    \
   1028 }
   1029 
   1030 #define GEN_VSX_HELPER_R2(name, op1, op2, inval, type)                        \
   1031 static void gen_##name(DisasContext *ctx)                                     \
   1032 {                                                                             \
   1033     TCGv_i32 opc;                                                             \
   1034     TCGv_ptr xt, xb;                                                          \
   1035     if (unlikely(!ctx->vsx_enabled)) {                                        \
   1036         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
   1037         return;                                                               \
   1038     }                                                                         \
   1039     opc = tcg_const_i32(ctx->opcode);                                         \
   1040     xt = gen_vsr_ptr(rD(ctx->opcode) + 32);                                   \
   1041     xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
   1042     gen_helper_##name(cpu_env, opc, xt, xb);                                  \
   1043     tcg_temp_free_i32(opc);                                                   \
   1044     tcg_temp_free_ptr(xt);                                                    \
   1045     tcg_temp_free_ptr(xb);                                                    \
   1046 }
   1047 
   1048 #define GEN_VSX_HELPER_R2_AB(name, op1, op2, inval, type)                     \
   1049 static void gen_##name(DisasContext *ctx)                                     \
   1050 {                                                                             \
   1051     TCGv_i32 opc;                                                             \
   1052     TCGv_ptr xa, xb;                                                          \
   1053     if (unlikely(!ctx->vsx_enabled)) {                                        \
   1054         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
   1055         return;                                                               \
   1056     }                                                                         \
   1057     opc = tcg_const_i32(ctx->opcode);                                         \
   1058     xa = gen_vsr_ptr(rA(ctx->opcode) + 32);                                   \
   1059     xb = gen_vsr_ptr(rB(ctx->opcode) + 32);                                   \
   1060     gen_helper_##name(cpu_env, opc, xa, xb);                                  \
   1061     tcg_temp_free_i32(opc);                                                   \
   1062     tcg_temp_free_ptr(xa);                                                    \
   1063     tcg_temp_free_ptr(xb);                                                    \
   1064 }
   1065 
   1066 #define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
   1067 static void gen_##name(DisasContext *ctx)                     \
   1068 {                                                             \
   1069     TCGv_i64 t0;                                              \
   1070     TCGv_i64 t1;                                              \
   1071     if (unlikely(!ctx->vsx_enabled)) {                        \
   1072         gen_exception(ctx, POWERPC_EXCP_VSXU);                \
   1073         return;                                               \
   1074     }                                                         \
   1075     t0 = tcg_temp_new_i64();                                  \
   1076     t1 = tcg_temp_new_i64();                                  \
   1077     get_cpu_vsr(t0, xB(ctx->opcode), true);                   \
   1078     gen_helper_##name(t1, cpu_env, t0);                       \
   1079     set_cpu_vsr(xT(ctx->opcode), t1, true);                   \
   1080     set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
   1081     tcg_temp_free_i64(t0);                                    \
   1082     tcg_temp_free_i64(t1);                                    \
   1083 }
   1084 
   1085 GEN_VSX_HELPER_X3(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
   1086 GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300)
   1087 GEN_VSX_HELPER_X3(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
   1088 GEN_VSX_HELPER_X3(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
   1089 GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300)
   1090 GEN_VSX_HELPER_X3(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
   1091 GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300)
   1092 GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
   1093 GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
   1094 GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
   1095 GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
   1096 GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
   1097 GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300)
   1098 GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300)
   1099 GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
   1100 GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
   1101 GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX)
   1102 GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX)
   1103 GEN_VSX_HELPER_X3(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
   1104 GEN_VSX_HELPER_X3(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
   1105 GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300)
   1106 GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
   1107 GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
   1108 GEN_VSX_HELPER_XT_XB_ENV(xscvdpspn, 0x16, 0x10, 0, PPC2_VSX207)
   1109 GEN_VSX_HELPER_R2(xscvqpsdz, 0x04, 0x1A, 0x19, PPC2_ISA300)
   1110 GEN_VSX_HELPER_R2(xscvqpswz, 0x04, 0x1A, 0x09, PPC2_ISA300)
   1111 GEN_VSX_HELPER_R2(xscvqpudz, 0x04, 0x1A, 0x11, PPC2_ISA300)
   1112 GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300)
   1113 GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
   1114 GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
   1115 GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
   1116 
   1117 /* test if +Inf */
   1118 static void gen_is_pos_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1119 {
   1120     uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
   1121     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1122                     tcg_constant_vec_matching(t, vece, exp_msk));
   1123 }
   1124 
   1125 /* test if -Inf */
   1126 static void gen_is_neg_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1127 {
   1128     uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
   1129     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1130     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1131                     tcg_constant_vec_matching(t, vece, sgn_msk | exp_msk));
   1132 }
   1133 
   1134 /* test if +Inf or -Inf */
   1135 static void gen_is_any_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1136 {
   1137     uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
   1138     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1139     tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
   1140     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1141                     tcg_constant_vec_matching(t, vece, exp_msk));
   1142 }
   1143 
   1144 /* test if +0 */
   1145 static void gen_is_pos_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1146 {
   1147     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1148                     tcg_constant_vec_matching(t, vece, 0));
   1149 }
   1150 
   1151 /* test if -0 */
   1152 static void gen_is_neg_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1153 {
   1154     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1155     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1156                     tcg_constant_vec_matching(t, vece, sgn_msk));
   1157 }
   1158 
   1159 /* test if +0 or -0 */
   1160 static void gen_is_any_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1161 {
   1162     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1163     tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
   1164     tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
   1165                     tcg_constant_vec_matching(t, vece, 0));
   1166 }
   1167 
   1168 /* test if +Denormal */
   1169 static void gen_is_pos_denormal(unsigned vece, TCGv_vec t,
   1170                                 TCGv_vec b, int64_t v)
   1171 {
   1172     uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
   1173     tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
   1174                     tcg_constant_vec_matching(t, vece, frc_msk));
   1175     tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
   1176                     tcg_constant_vec_matching(t, vece, 0));
   1177     tcg_gen_and_vec(vece, t, t, b);
   1178 }
   1179 
   1180 /* test if -Denormal */
   1181 static void gen_is_neg_denormal(unsigned vece, TCGv_vec t,
   1182                                 TCGv_vec b, int64_t v)
   1183 {
   1184     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1185     uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
   1186     tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
   1187                     tcg_constant_vec_matching(t, vece, sgn_msk | frc_msk));
   1188     tcg_gen_cmp_vec(TCG_COND_GTU, vece, b, b,
   1189                     tcg_constant_vec_matching(t, vece, sgn_msk));
   1190     tcg_gen_and_vec(vece, t, t, b);
   1191 }
   1192 
   1193 /* test if +Denormal or -Denormal */
   1194 static void gen_is_any_denormal(unsigned vece, TCGv_vec t,
   1195                                 TCGv_vec b, int64_t v)
   1196 {
   1197     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1198     uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
   1199     tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
   1200     tcg_gen_cmp_vec(TCG_COND_LE, vece, t, b,
   1201                     tcg_constant_vec_matching(t, vece, frc_msk));
   1202     tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
   1203                     tcg_constant_vec_matching(t, vece, 0));
   1204     tcg_gen_and_vec(vece, t, t, b);
   1205 }
   1206 
   1207 /* test if NaN */
   1208 static void gen_is_nan(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
   1209 {
   1210     uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
   1211     uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
   1212     tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
   1213     tcg_gen_cmp_vec(TCG_COND_GT, vece, t, b,
   1214                     tcg_constant_vec_matching(t, vece, exp_msk));
   1215 }
   1216 
   1217 static bool do_xvtstdc(DisasContext *ctx, arg_XX2_uim *a, unsigned vece)
   1218 {
   1219     static const TCGOpcode vecop_list[] = {
   1220         INDEX_op_cmp_vec, 0
   1221     };
   1222 
   1223     GVecGen2i op = {
   1224         .fnoi = (vece == MO_32) ? gen_helper_XVTSTDCSP : gen_helper_XVTSTDCDP,
   1225         .vece = vece,
   1226         .opt_opc = vecop_list
   1227     };
   1228 
   1229     REQUIRE_VSX(ctx);
   1230 
   1231     switch (a->uim) {
   1232     case 0:
   1233         set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
   1234         set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
   1235         return true;
   1236     case ((1 << 0) | (1 << 1)):
   1237         /* test if +Denormal or -Denormal */
   1238         op.fniv = gen_is_any_denormal;
   1239         break;
   1240     case (1 << 0):
   1241         /* test if -Denormal */
   1242         op.fniv = gen_is_neg_denormal;
   1243         break;
   1244     case (1 << 1):
   1245         /* test if +Denormal */
   1246         op.fniv = gen_is_pos_denormal;
   1247         break;
   1248     case ((1 << 2) | (1 << 3)):
   1249         /* test if +0 or -0 */
   1250         op.fniv = gen_is_any_zero;
   1251         break;
   1252     case (1 << 2):
   1253         /* test if -0 */
   1254         op.fniv = gen_is_neg_zero;
   1255         break;
   1256     case (1 << 3):
   1257         /* test if +0 */
   1258         op.fniv = gen_is_pos_zero;
   1259         break;
   1260     case ((1 << 4) | (1 << 5)):
   1261         /* test if +Inf or -Inf */
   1262         op.fniv = gen_is_any_inf;
   1263         break;
   1264     case (1 << 4):
   1265         /* test if -Inf */
   1266         op.fniv = gen_is_neg_inf;
   1267         break;
   1268     case (1 << 5):
   1269         /* test if +Inf */
   1270         op.fniv = gen_is_pos_inf;
   1271         break;
   1272     case (1 << 6):
   1273         /* test if NaN */
   1274         op.fniv = gen_is_nan;
   1275         break;
   1276     }
   1277     tcg_gen_gvec_2i(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
   1278                     16, 16, a->uim, &op);
   1279 
   1280     return true;
   1281 }
   1282 
   1283 TRANS_FLAGS2(VSX, XVTSTDCSP, do_xvtstdc, MO_32)
   1284 TRANS_FLAGS2(VSX, XVTSTDCDP, do_xvtstdc, MO_64)
   1285 
   1286 static bool do_XX2_bf_uim(DisasContext *ctx, arg_XX2_bf_uim *a, bool vsr,
   1287                      void (*gen_helper)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_ptr))
   1288 {
   1289     TCGv_ptr xb;
   1290 
   1291     REQUIRE_VSX(ctx);
   1292     xb = vsr ? gen_vsr_ptr(a->xb) : gen_avr_ptr(a->xb);
   1293     gen_helper(cpu_env, tcg_constant_i32(a->bf), tcg_constant_i32(a->uim), xb);
   1294     tcg_temp_free_ptr(xb);
   1295 
   1296     return true;
   1297 }
   1298 
   1299 TRANS_FLAGS2(ISA300, XSTSTDCSP, do_XX2_bf_uim, true, gen_helper_XSTSTDCSP)
   1300 TRANS_FLAGS2(ISA300, XSTSTDCDP, do_XX2_bf_uim, true, gen_helper_XSTSTDCDP)
   1301 TRANS_FLAGS2(ISA300, XSTSTDCQP, do_XX2_bf_uim, false, gen_helper_XSTSTDCQP)
   1302 
   1303 bool trans_XSCVSPDPN(DisasContext *ctx, arg_XX2 *a)
   1304 {
   1305     TCGv_i64 tmp;
   1306 
   1307     REQUIRE_INSNS_FLAGS2(ctx, VSX207);
   1308     REQUIRE_VSX(ctx);
   1309 
   1310     tmp = tcg_temp_new_i64();
   1311     get_cpu_vsr(tmp, a->xb, true);
   1312 
   1313     gen_helper_XSCVSPDPN(tmp, tmp);
   1314 
   1315     set_cpu_vsr(a->xt, tmp, true);
   1316     set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
   1317 
   1318     tcg_temp_free_i64(tmp);
   1319 
   1320     return true;
   1321 }
   1322 
   1323 GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
   1324 GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
   1325 GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
   1326 GEN_VSX_HELPER_X2(xscvdpuxws, 0x10, 0x04, 0, PPC2_VSX)
   1327 GEN_VSX_HELPER_X2(xscvsxddp, 0x10, 0x17, 0, PPC2_VSX)
   1328 GEN_VSX_HELPER_R2(xscvudqp, 0x04, 0x1A, 0x02, PPC2_ISA300)
   1329 GEN_VSX_HELPER_X2(xscvuxddp, 0x10, 0x16, 0, PPC2_VSX)
   1330 GEN_VSX_HELPER_X2(xsrdpi, 0x12, 0x04, 0, PPC2_VSX)
   1331 GEN_VSX_HELPER_X2(xsrdpic, 0x16, 0x06, 0, PPC2_VSX)
   1332 GEN_VSX_HELPER_X2(xsrdpim, 0x12, 0x07, 0, PPC2_VSX)
   1333 GEN_VSX_HELPER_X2(xsrdpip, 0x12, 0x06, 0, PPC2_VSX)
   1334 GEN_VSX_HELPER_X2(xsrdpiz, 0x12, 0x05, 0, PPC2_VSX)
   1335 GEN_VSX_HELPER_XT_XB_ENV(xsrsp, 0x12, 0x11, 0, PPC2_VSX207)
   1336 GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300)
   1337 GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300)
   1338 GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300)
   1339 GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300)
   1340 GEN_VSX_HELPER_X3(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
   1341 GEN_VSX_HELPER_X3(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
   1342 GEN_VSX_HELPER_X3(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
   1343 GEN_VSX_HELPER_X3(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
   1344 GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
   1345 GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
   1346 GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
   1347 GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
   1348 GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
   1349 
   1350 GEN_VSX_HELPER_X3(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
   1351 GEN_VSX_HELPER_X3(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
   1352 GEN_VSX_HELPER_X3(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
   1353 GEN_VSX_HELPER_X3(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
   1354 GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
   1355 GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
   1356 GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
   1357 GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
   1358 GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
   1359 GEN_VSX_HELPER_X3(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
   1360 GEN_VSX_HELPER_X3(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
   1361 GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
   1362 GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
   1363 GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
   1364 GEN_VSX_HELPER_X2(xvcvdpuxds, 0x10, 0x1C, 0, PPC2_VSX)
   1365 GEN_VSX_HELPER_X2(xvcvdpuxws, 0x10, 0x0C, 0, PPC2_VSX)
   1366 GEN_VSX_HELPER_X2(xvcvsxddp, 0x10, 0x1F, 0, PPC2_VSX)
   1367 GEN_VSX_HELPER_X2(xvcvuxddp, 0x10, 0x1E, 0, PPC2_VSX)
   1368 GEN_VSX_HELPER_X2(xvcvsxwdp, 0x10, 0x0F, 0, PPC2_VSX)
   1369 GEN_VSX_HELPER_X2(xvcvuxwdp, 0x10, 0x0E, 0, PPC2_VSX)
   1370 GEN_VSX_HELPER_X2(xvrdpi, 0x12, 0x0C, 0, PPC2_VSX)
   1371 GEN_VSX_HELPER_X2(xvrdpic, 0x16, 0x0E, 0, PPC2_VSX)
   1372 GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
   1373 GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
   1374 GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
   1375 
   1376 GEN_VSX_HELPER_X3(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
   1377 GEN_VSX_HELPER_X3(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
   1378 GEN_VSX_HELPER_X3(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
   1379 GEN_VSX_HELPER_X3(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
   1380 GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
   1381 GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
   1382 GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
   1383 GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
   1384 GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
   1385 GEN_VSX_HELPER_X3(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
   1386 GEN_VSX_HELPER_X3(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
   1387 GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
   1388 GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300)
   1389 GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300)
   1390 GEN_VSX_HELPER_X2(xvcvspsxds, 0x10, 0x19, 0, PPC2_VSX)
   1391 GEN_VSX_HELPER_X2(xvcvspsxws, 0x10, 0x09, 0, PPC2_VSX)
   1392 GEN_VSX_HELPER_X2(xvcvspuxds, 0x10, 0x18, 0, PPC2_VSX)
   1393 GEN_VSX_HELPER_X2(xvcvspuxws, 0x10, 0x08, 0, PPC2_VSX)
   1394 GEN_VSX_HELPER_X2(xvcvsxdsp, 0x10, 0x1B, 0, PPC2_VSX)
   1395 GEN_VSX_HELPER_X2(xvcvuxdsp, 0x10, 0x1A, 0, PPC2_VSX)
   1396 GEN_VSX_HELPER_X2(xvcvsxwsp, 0x10, 0x0B, 0, PPC2_VSX)
   1397 GEN_VSX_HELPER_X2(xvcvuxwsp, 0x10, 0x0A, 0, PPC2_VSX)
   1398 GEN_VSX_HELPER_X2(xvrspi, 0x12, 0x08, 0, PPC2_VSX)
   1399 GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
   1400 GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
   1401 GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
   1402 GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
   1403 
   1404 static bool trans_XXPERM(DisasContext *ctx, arg_XX3 *a)
   1405 {
   1406     TCGv_ptr xt, xa, xb;
   1407 
   1408     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   1409     REQUIRE_VSX(ctx);
   1410 
   1411     xt = gen_vsr_ptr(a->xt);
   1412     xa = gen_vsr_ptr(a->xa);
   1413     xb = gen_vsr_ptr(a->xb);
   1414 
   1415     gen_helper_VPERM(xt, xa, xt, xb);
   1416 
   1417     tcg_temp_free_ptr(xt);
   1418     tcg_temp_free_ptr(xa);
   1419     tcg_temp_free_ptr(xb);
   1420 
   1421     return true;
   1422 }
   1423 
   1424 static bool trans_XXPERMR(DisasContext *ctx, arg_XX3 *a)
   1425 {
   1426     TCGv_ptr xt, xa, xb;
   1427 
   1428     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   1429     REQUIRE_VSX(ctx);
   1430 
   1431     xt = gen_vsr_ptr(a->xt);
   1432     xa = gen_vsr_ptr(a->xa);
   1433     xb = gen_vsr_ptr(a->xb);
   1434 
   1435     gen_helper_VPERMR(xt, xa, xt, xb);
   1436 
   1437     tcg_temp_free_ptr(xt);
   1438     tcg_temp_free_ptr(xa);
   1439     tcg_temp_free_ptr(xb);
   1440 
   1441     return true;
   1442 }
   1443 
   1444 static bool trans_XXPERMDI(DisasContext *ctx, arg_XX3_dm *a)
   1445 {
   1446     TCGv_i64 t0, t1;
   1447 
   1448     REQUIRE_INSNS_FLAGS2(ctx, VSX);
   1449     REQUIRE_VSX(ctx);
   1450 
   1451     t0 = tcg_temp_new_i64();
   1452 
   1453     if (unlikely(a->xt == a->xa || a->xt == a->xb)) {
   1454         t1 = tcg_temp_new_i64();
   1455 
   1456         get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
   1457         get_cpu_vsr(t1, a->xb, (a->dm & 1) == 0);
   1458 
   1459         set_cpu_vsr(a->xt, t0, true);
   1460         set_cpu_vsr(a->xt, t1, false);
   1461 
   1462         tcg_temp_free_i64(t1);
   1463     } else {
   1464         get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
   1465         set_cpu_vsr(a->xt, t0, true);
   1466 
   1467         get_cpu_vsr(t0, a->xb, (a->dm & 1) == 0);
   1468         set_cpu_vsr(a->xt, t0, false);
   1469     }
   1470 
   1471     tcg_temp_free_i64(t0);
   1472 
   1473     return true;
   1474 }
   1475 
   1476 static bool trans_XXPERMX(DisasContext *ctx, arg_8RR_XX4_uim3 *a)
   1477 {
   1478     TCGv_ptr xt, xa, xb, xc;
   1479 
   1480     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1481     REQUIRE_VSX(ctx);
   1482 
   1483     xt = gen_vsr_ptr(a->xt);
   1484     xa = gen_vsr_ptr(a->xa);
   1485     xb = gen_vsr_ptr(a->xb);
   1486     xc = gen_vsr_ptr(a->xc);
   1487 
   1488     gen_helper_XXPERMX(xt, xa, xb, xc, tcg_constant_tl(a->uim3));
   1489 
   1490     tcg_temp_free_ptr(xt);
   1491     tcg_temp_free_ptr(xa);
   1492     tcg_temp_free_ptr(xb);
   1493     tcg_temp_free_ptr(xc);
   1494 
   1495     return true;
   1496 }
   1497 
   1498 typedef void (*xxgenpcv_genfn)(TCGv_ptr, TCGv_ptr);
   1499 
   1500 static bool do_xxgenpcv(DisasContext *ctx, arg_X_imm5 *a,
   1501                         const xxgenpcv_genfn fn[4])
   1502 {
   1503     TCGv_ptr xt, vrb;
   1504 
   1505     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1506     REQUIRE_VSX(ctx);
   1507 
   1508     if (a->imm & ~0x3) {
   1509         gen_invalid(ctx);
   1510         return true;
   1511     }
   1512 
   1513     xt = gen_vsr_ptr(a->xt);
   1514     vrb = gen_avr_ptr(a->vrb);
   1515 
   1516     fn[a->imm](xt, vrb);
   1517 
   1518     tcg_temp_free_ptr(xt);
   1519     tcg_temp_free_ptr(vrb);
   1520 
   1521     return true;
   1522 }
   1523 
   1524 #define XXGENPCV(NAME) \
   1525     static bool trans_##NAME(DisasContext *ctx, arg_X_imm5 *a)  \
   1526     {                                                           \
   1527         static const xxgenpcv_genfn fn[4] = {                   \
   1528             gen_helper_##NAME##_be_exp,                         \
   1529             gen_helper_##NAME##_be_comp,                        \
   1530             gen_helper_##NAME##_le_exp,                         \
   1531             gen_helper_##NAME##_le_comp,                        \
   1532         };                                                      \
   1533         return do_xxgenpcv(ctx, a, fn);                         \
   1534     }
   1535 
   1536 XXGENPCV(XXGENPCVBM)
   1537 XXGENPCV(XXGENPCVHM)
   1538 XXGENPCV(XXGENPCVWM)
   1539 XXGENPCV(XXGENPCVDM)
   1540 #undef XXGENPCV
   1541 
   1542 static bool do_xsmadd(DisasContext *ctx, int tgt, int src1, int src2, int src3,
   1543         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   1544 {
   1545     TCGv_ptr t, s1, s2, s3;
   1546 
   1547     t = gen_vsr_ptr(tgt);
   1548     s1 = gen_vsr_ptr(src1);
   1549     s2 = gen_vsr_ptr(src2);
   1550     s3 = gen_vsr_ptr(src3);
   1551 
   1552     gen_helper(cpu_env, t, s1, s2, s3);
   1553 
   1554     tcg_temp_free_ptr(t);
   1555     tcg_temp_free_ptr(s1);
   1556     tcg_temp_free_ptr(s2);
   1557     tcg_temp_free_ptr(s3);
   1558 
   1559     return true;
   1560 }
   1561 
   1562 static bool do_xsmadd_XX3(DisasContext *ctx, arg_XX3 *a, bool type_a,
   1563         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   1564 {
   1565     REQUIRE_VSX(ctx);
   1566 
   1567     if (type_a) {
   1568         return do_xsmadd(ctx, a->xt, a->xa, a->xt, a->xb, gen_helper);
   1569     }
   1570     return do_xsmadd(ctx, a->xt, a->xa, a->xb, a->xt, gen_helper);
   1571 }
   1572 
   1573 TRANS_FLAGS2(VSX, XSMADDADP, do_xsmadd_XX3, true, gen_helper_XSMADDDP)
   1574 TRANS_FLAGS2(VSX, XSMADDMDP, do_xsmadd_XX3, false, gen_helper_XSMADDDP)
   1575 TRANS_FLAGS2(VSX, XSMSUBADP, do_xsmadd_XX3, true, gen_helper_XSMSUBDP)
   1576 TRANS_FLAGS2(VSX, XSMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSMSUBDP)
   1577 TRANS_FLAGS2(VSX, XSNMADDADP, do_xsmadd_XX3, true, gen_helper_XSNMADDDP)
   1578 TRANS_FLAGS2(VSX, XSNMADDMDP, do_xsmadd_XX3, false, gen_helper_XSNMADDDP)
   1579 TRANS_FLAGS2(VSX, XSNMSUBADP, do_xsmadd_XX3, true, gen_helper_XSNMSUBDP)
   1580 TRANS_FLAGS2(VSX, XSNMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSNMSUBDP)
   1581 TRANS_FLAGS2(VSX207, XSMADDASP, do_xsmadd_XX3, true, gen_helper_XSMADDSP)
   1582 TRANS_FLAGS2(VSX207, XSMADDMSP, do_xsmadd_XX3, false, gen_helper_XSMADDSP)
   1583 TRANS_FLAGS2(VSX207, XSMSUBASP, do_xsmadd_XX3, true, gen_helper_XSMSUBSP)
   1584 TRANS_FLAGS2(VSX207, XSMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSMSUBSP)
   1585 TRANS_FLAGS2(VSX207, XSNMADDASP, do_xsmadd_XX3, true, gen_helper_XSNMADDSP)
   1586 TRANS_FLAGS2(VSX207, XSNMADDMSP, do_xsmadd_XX3, false, gen_helper_XSNMADDSP)
   1587 TRANS_FLAGS2(VSX207, XSNMSUBASP, do_xsmadd_XX3, true, gen_helper_XSNMSUBSP)
   1588 TRANS_FLAGS2(VSX207, XSNMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSNMSUBSP)
   1589 
   1590 static bool do_xsmadd_X(DisasContext *ctx, arg_X_rc *a,
   1591         void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr),
   1592         void (*gen_helper_ro)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   1593 {
   1594     int vrt, vra, vrb;
   1595 
   1596     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   1597     REQUIRE_VSX(ctx);
   1598 
   1599     vrt = a->rt + 32;
   1600     vra = a->ra + 32;
   1601     vrb = a->rb + 32;
   1602 
   1603     if (a->rc) {
   1604         return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper_ro);
   1605     }
   1606 
   1607     return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper);
   1608 }
   1609 
   1610 TRANS(XSMADDQP, do_xsmadd_X, gen_helper_XSMADDQP, gen_helper_XSMADDQPO)
   1611 TRANS(XSMSUBQP, do_xsmadd_X, gen_helper_XSMSUBQP, gen_helper_XSMSUBQPO)
   1612 TRANS(XSNMADDQP, do_xsmadd_X, gen_helper_XSNMADDQP, gen_helper_XSNMADDQPO)
   1613 TRANS(XSNMSUBQP, do_xsmadd_X, gen_helper_XSNMSUBQP, gen_helper_XSNMSUBQPO)
   1614 
   1615 #define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type)             \
   1616 static void gen_##name(DisasContext *ctx)                                     \
   1617 {                                                                             \
   1618     TCGv_ptr xt, s1, s2, s3;                                                  \
   1619     if (unlikely(!ctx->vsx_enabled)) {                                        \
   1620         gen_exception(ctx, POWERPC_EXCP_VSXU);                                \
   1621         return;                                                               \
   1622     }                                                                         \
   1623     xt = gen_vsr_ptr(xT(ctx->opcode));                                        \
   1624     s1 = gen_vsr_ptr(xA(ctx->opcode));                                        \
   1625     if (ctx->opcode & PPC_BIT32(25)) {                                        \
   1626         /*                                                                    \
   1627          * AxT + B                                                            \
   1628          */                                                                   \
   1629         s2 = gen_vsr_ptr(xB(ctx->opcode));                                    \
   1630         s3 = gen_vsr_ptr(xT(ctx->opcode));                                    \
   1631     } else {                                                                  \
   1632         /*                                                                    \
   1633          * AxB + T                                                            \
   1634          */                                                                   \
   1635         s2 = gen_vsr_ptr(xT(ctx->opcode));                                    \
   1636         s3 = gen_vsr_ptr(xB(ctx->opcode));                                    \
   1637     }                                                                         \
   1638     gen_helper_##name(cpu_env, xt, s1, s2, s3);                               \
   1639     tcg_temp_free_ptr(xt);                                                    \
   1640     tcg_temp_free_ptr(s1);                                                    \
   1641     tcg_temp_free_ptr(s2);                                                    \
   1642     tcg_temp_free_ptr(s3);                                                    \
   1643 }
   1644 
   1645 GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX)
   1646 GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX)
   1647 GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX)
   1648 GEN_VSX_HELPER_VSX_MADD(xvnmsubdp, 0x04, 0x1E, 0x1F, 0, PPC2_VSX)
   1649 GEN_VSX_HELPER_VSX_MADD(xvmaddsp, 0x04, 0x08, 0x09, 0, PPC2_VSX)
   1650 GEN_VSX_HELPER_VSX_MADD(xvmsubsp, 0x04, 0x0A, 0x0B, 0, PPC2_VSX)
   1651 GEN_VSX_HELPER_VSX_MADD(xvnmaddsp, 0x04, 0x18, 0x19, 0, PPC2_VSX)
   1652 GEN_VSX_HELPER_VSX_MADD(xvnmsubsp, 0x04, 0x1A, 0x1B, 0, PPC2_VSX)
   1653 
   1654 static void gen_xxbrd(DisasContext *ctx)
   1655 {
   1656     TCGv_i64 xth;
   1657     TCGv_i64 xtl;
   1658     TCGv_i64 xbh;
   1659     TCGv_i64 xbl;
   1660 
   1661     if (unlikely(!ctx->vsx_enabled)) {
   1662         gen_exception(ctx, POWERPC_EXCP_VSXU);
   1663         return;
   1664     }
   1665     xth = tcg_temp_new_i64();
   1666     xtl = tcg_temp_new_i64();
   1667     xbh = tcg_temp_new_i64();
   1668     xbl = tcg_temp_new_i64();
   1669     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   1670     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   1671 
   1672     tcg_gen_bswap64_i64(xth, xbh);
   1673     tcg_gen_bswap64_i64(xtl, xbl);
   1674     set_cpu_vsr(xT(ctx->opcode), xth, true);
   1675     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   1676 
   1677     tcg_temp_free_i64(xth);
   1678     tcg_temp_free_i64(xtl);
   1679     tcg_temp_free_i64(xbh);
   1680     tcg_temp_free_i64(xbl);
   1681 }
   1682 
   1683 static void gen_xxbrh(DisasContext *ctx)
   1684 {
   1685     TCGv_i64 xth;
   1686     TCGv_i64 xtl;
   1687     TCGv_i64 xbh;
   1688     TCGv_i64 xbl;
   1689 
   1690     if (unlikely(!ctx->vsx_enabled)) {
   1691         gen_exception(ctx, POWERPC_EXCP_VSXU);
   1692         return;
   1693     }
   1694     xth = tcg_temp_new_i64();
   1695     xtl = tcg_temp_new_i64();
   1696     xbh = tcg_temp_new_i64();
   1697     xbl = tcg_temp_new_i64();
   1698     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   1699     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   1700 
   1701     gen_bswap16x8(xth, xtl, xbh, xbl);
   1702     set_cpu_vsr(xT(ctx->opcode), xth, true);
   1703     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   1704 
   1705     tcg_temp_free_i64(xth);
   1706     tcg_temp_free_i64(xtl);
   1707     tcg_temp_free_i64(xbh);
   1708     tcg_temp_free_i64(xbl);
   1709 }
   1710 
   1711 static void gen_xxbrq(DisasContext *ctx)
   1712 {
   1713     TCGv_i64 xth;
   1714     TCGv_i64 xtl;
   1715     TCGv_i64 xbh;
   1716     TCGv_i64 xbl;
   1717     TCGv_i64 t0;
   1718 
   1719     if (unlikely(!ctx->vsx_enabled)) {
   1720         gen_exception(ctx, POWERPC_EXCP_VSXU);
   1721         return;
   1722     }
   1723     xth = tcg_temp_new_i64();
   1724     xtl = tcg_temp_new_i64();
   1725     xbh = tcg_temp_new_i64();
   1726     xbl = tcg_temp_new_i64();
   1727     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   1728     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   1729     t0 = tcg_temp_new_i64();
   1730 
   1731     tcg_gen_bswap64_i64(t0, xbl);
   1732     tcg_gen_bswap64_i64(xtl, xbh);
   1733     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   1734     tcg_gen_mov_i64(xth, t0);
   1735     set_cpu_vsr(xT(ctx->opcode), xth, true);
   1736 
   1737     tcg_temp_free_i64(t0);
   1738     tcg_temp_free_i64(xth);
   1739     tcg_temp_free_i64(xtl);
   1740     tcg_temp_free_i64(xbh);
   1741     tcg_temp_free_i64(xbl);
   1742 }
   1743 
   1744 static void gen_xxbrw(DisasContext *ctx)
   1745 {
   1746     TCGv_i64 xth;
   1747     TCGv_i64 xtl;
   1748     TCGv_i64 xbh;
   1749     TCGv_i64 xbl;
   1750 
   1751     if (unlikely(!ctx->vsx_enabled)) {
   1752         gen_exception(ctx, POWERPC_EXCP_VSXU);
   1753         return;
   1754     }
   1755     xth = tcg_temp_new_i64();
   1756     xtl = tcg_temp_new_i64();
   1757     xbh = tcg_temp_new_i64();
   1758     xbl = tcg_temp_new_i64();
   1759     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   1760     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   1761 
   1762     gen_bswap32x4(xth, xtl, xbh, xbl);
   1763     set_cpu_vsr(xT(ctx->opcode), xth, true);
   1764     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   1765 
   1766     tcg_temp_free_i64(xth);
   1767     tcg_temp_free_i64(xtl);
   1768     tcg_temp_free_i64(xbh);
   1769     tcg_temp_free_i64(xbl);
   1770 }
   1771 
   1772 #define VSX_LOGICAL(name, vece, tcg_op)                              \
   1773 static void glue(gen_, name)(DisasContext *ctx)                      \
   1774     {                                                                \
   1775         if (unlikely(!ctx->vsx_enabled)) {                           \
   1776             gen_exception(ctx, POWERPC_EXCP_VSXU);                   \
   1777             return;                                                  \
   1778         }                                                            \
   1779         tcg_op(vece, vsr_full_offset(xT(ctx->opcode)),               \
   1780                vsr_full_offset(xA(ctx->opcode)),                     \
   1781                vsr_full_offset(xB(ctx->opcode)), 16, 16);            \
   1782     }
   1783 
   1784 VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
   1785 VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
   1786 VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
   1787 VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
   1788 VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
   1789 VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
   1790 VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
   1791 VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
   1792 
   1793 #define VSX_XXMRG(name, high)                               \
   1794 static void glue(gen_, name)(DisasContext *ctx)             \
   1795     {                                                       \
   1796         TCGv_i64 a0, a1, b0, b1, tmp;                       \
   1797         if (unlikely(!ctx->vsx_enabled)) {                  \
   1798             gen_exception(ctx, POWERPC_EXCP_VSXU);          \
   1799             return;                                         \
   1800         }                                                   \
   1801         a0 = tcg_temp_new_i64();                            \
   1802         a1 = tcg_temp_new_i64();                            \
   1803         b0 = tcg_temp_new_i64();                            \
   1804         b1 = tcg_temp_new_i64();                            \
   1805         tmp = tcg_temp_new_i64();                           \
   1806         get_cpu_vsr(a0, xA(ctx->opcode), high);             \
   1807         get_cpu_vsr(a1, xA(ctx->opcode), high);             \
   1808         get_cpu_vsr(b0, xB(ctx->opcode), high);             \
   1809         get_cpu_vsr(b1, xB(ctx->opcode), high);             \
   1810         tcg_gen_shri_i64(a0, a0, 32);                       \
   1811         tcg_gen_shri_i64(b0, b0, 32);                       \
   1812         tcg_gen_deposit_i64(tmp, b0, a0, 32, 32);           \
   1813         set_cpu_vsr(xT(ctx->opcode), tmp, true);            \
   1814         tcg_gen_deposit_i64(tmp, b1, a1, 32, 32);           \
   1815         set_cpu_vsr(xT(ctx->opcode), tmp, false);           \
   1816         tcg_temp_free_i64(a0);                              \
   1817         tcg_temp_free_i64(a1);                              \
   1818         tcg_temp_free_i64(b0);                              \
   1819         tcg_temp_free_i64(b1);                              \
   1820         tcg_temp_free_i64(tmp);                             \
   1821     }
   1822 
   1823 VSX_XXMRG(xxmrghw, 1)
   1824 VSX_XXMRG(xxmrglw, 0)
   1825 
   1826 static bool trans_XXSEL(DisasContext *ctx, arg_XX4 *a)
   1827 {
   1828     REQUIRE_INSNS_FLAGS2(ctx, VSX);
   1829     REQUIRE_VSX(ctx);
   1830 
   1831     tcg_gen_gvec_bitsel(MO_64, vsr_full_offset(a->xt), vsr_full_offset(a->xc),
   1832                         vsr_full_offset(a->xb), vsr_full_offset(a->xa), 16, 16);
   1833 
   1834     return true;
   1835 }
   1836 
   1837 static bool trans_XXSPLTW(DisasContext *ctx, arg_XX2_uim *a)
   1838 {
   1839     int tofs, bofs;
   1840 
   1841     REQUIRE_VSX(ctx);
   1842 
   1843     tofs = vsr_full_offset(a->xt);
   1844     bofs = vsr_full_offset(a->xb);
   1845     bofs += a->uim << MO_32;
   1846 #if !HOST_BIG_ENDIAN
   1847     bofs ^= 8 | 4;
   1848 #endif
   1849 
   1850     tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
   1851     return true;
   1852 }
   1853 
   1854 #define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
   1855 
   1856 static bool trans_XXSPLTIB(DisasContext *ctx, arg_X_imm8 *a)
   1857 {
   1858     if (a->xt < 32) {
   1859         REQUIRE_VSX(ctx);
   1860     } else {
   1861         REQUIRE_VECTOR(ctx);
   1862     }
   1863     tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(a->xt), 16, 16, a->imm);
   1864     return true;
   1865 }
   1866 
   1867 static bool trans_XXSPLTIW(DisasContext *ctx, arg_8RR_D *a)
   1868 {
   1869     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1870     REQUIRE_VSX(ctx);
   1871 
   1872     tcg_gen_gvec_dup_imm(MO_32, vsr_full_offset(a->xt), 16, 16, a->si);
   1873 
   1874     return true;
   1875 }
   1876 
   1877 static bool trans_XXSPLTIDP(DisasContext *ctx, arg_8RR_D *a)
   1878 {
   1879     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1880     REQUIRE_VSX(ctx);
   1881 
   1882     tcg_gen_gvec_dup_imm(MO_64, vsr_full_offset(a->xt), 16, 16,
   1883                          helper_todouble(a->si));
   1884     return true;
   1885 }
   1886 
   1887 static bool trans_XXSPLTI32DX(DisasContext *ctx, arg_8RR_D_IX *a)
   1888 {
   1889     TCGv_i32 imm;
   1890 
   1891     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1892     REQUIRE_VSX(ctx);
   1893 
   1894     imm = tcg_constant_i32(a->si);
   1895 
   1896     tcg_gen_st_i32(imm, cpu_env,
   1897         offsetof(CPUPPCState, vsr[a->xt].VsrW(0 + a->ix)));
   1898     tcg_gen_st_i32(imm, cpu_env,
   1899         offsetof(CPUPPCState, vsr[a->xt].VsrW(2 + a->ix)));
   1900 
   1901     return true;
   1902 }
   1903 
   1904 static bool trans_LXVKQ(DisasContext *ctx, arg_X_uim5 *a)
   1905 {
   1906     static const uint64_t values[32] = {
   1907         0, /* Unspecified */
   1908         0x3FFF000000000000llu, /* QP +1.0 */
   1909         0x4000000000000000llu, /* QP +2.0 */
   1910         0x4000800000000000llu, /* QP +3.0 */
   1911         0x4001000000000000llu, /* QP +4.0 */
   1912         0x4001400000000000llu, /* QP +5.0 */
   1913         0x4001800000000000llu, /* QP +6.0 */
   1914         0x4001C00000000000llu, /* QP +7.0 */
   1915         0x7FFF000000000000llu, /* QP +Inf */
   1916         0x7FFF800000000000llu, /* QP dQNaN */
   1917         0, /* Unspecified */
   1918         0, /* Unspecified */
   1919         0, /* Unspecified */
   1920         0, /* Unspecified */
   1921         0, /* Unspecified */
   1922         0, /* Unspecified */
   1923         0x8000000000000000llu, /* QP -0.0 */
   1924         0xBFFF000000000000llu, /* QP -1.0 */
   1925         0xC000000000000000llu, /* QP -2.0 */
   1926         0xC000800000000000llu, /* QP -3.0 */
   1927         0xC001000000000000llu, /* QP -4.0 */
   1928         0xC001400000000000llu, /* QP -5.0 */
   1929         0xC001800000000000llu, /* QP -6.0 */
   1930         0xC001C00000000000llu, /* QP -7.0 */
   1931         0xFFFF000000000000llu, /* QP -Inf */
   1932     };
   1933 
   1934     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1935     REQUIRE_VSX(ctx);
   1936 
   1937     if (values[a->uim]) {
   1938         set_cpu_vsr(a->xt, tcg_constant_i64(0x0), false);
   1939         set_cpu_vsr(a->xt, tcg_constant_i64(values[a->uim]), true);
   1940     } else {
   1941         gen_invalid(ctx);
   1942     }
   1943 
   1944     return true;
   1945 }
   1946 
   1947 static bool trans_XVTLSBB(DisasContext *ctx, arg_XX2_bf_xb *a)
   1948 {
   1949     TCGv_i64 xb, t0, t1, all_true, all_false, mask, zero;
   1950 
   1951     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   1952     REQUIRE_VSX(ctx);
   1953 
   1954     xb = tcg_temp_new_i64();
   1955     t0 = tcg_temp_new_i64();
   1956     t1 = tcg_temp_new_i64();
   1957     all_true = tcg_temp_new_i64();
   1958     all_false = tcg_temp_new_i64();
   1959     mask = tcg_constant_i64(dup_const(MO_8, 1));
   1960     zero = tcg_constant_i64(0);
   1961 
   1962     get_cpu_vsr(xb, a->xb, true);
   1963     tcg_gen_and_i64(t0, mask, xb);
   1964     get_cpu_vsr(xb, a->xb, false);
   1965     tcg_gen_and_i64(t1, mask, xb);
   1966 
   1967     tcg_gen_or_i64(all_false, t0, t1);
   1968     tcg_gen_and_i64(all_true, t0, t1);
   1969 
   1970     tcg_gen_setcond_i64(TCG_COND_EQ, all_false, all_false, zero);
   1971     tcg_gen_shli_i64(all_false, all_false, 1);
   1972     tcg_gen_setcond_i64(TCG_COND_EQ, all_true, all_true, mask);
   1973     tcg_gen_shli_i64(all_true, all_true, 3);
   1974 
   1975     tcg_gen_or_i64(t0, all_false, all_true);
   1976     tcg_gen_extrl_i64_i32(cpu_crf[a->bf], t0);
   1977 
   1978     tcg_temp_free_i64(xb);
   1979     tcg_temp_free_i64(t0);
   1980     tcg_temp_free_i64(t1);
   1981     tcg_temp_free_i64(all_true);
   1982     tcg_temp_free_i64(all_false);
   1983 
   1984     return true;
   1985 }
   1986 
   1987 static void gen_xxsldwi(DisasContext *ctx)
   1988 {
   1989     TCGv_i64 xth, xtl;
   1990     if (unlikely(!ctx->vsx_enabled)) {
   1991         gen_exception(ctx, POWERPC_EXCP_VSXU);
   1992         return;
   1993     }
   1994     xth = tcg_temp_new_i64();
   1995     xtl = tcg_temp_new_i64();
   1996 
   1997     switch (SHW(ctx->opcode)) {
   1998         case 0: {
   1999             get_cpu_vsr(xth, xA(ctx->opcode), true);
   2000             get_cpu_vsr(xtl, xA(ctx->opcode), false);
   2001             break;
   2002         }
   2003         case 1: {
   2004             TCGv_i64 t0 = tcg_temp_new_i64();
   2005             get_cpu_vsr(xth, xA(ctx->opcode), true);
   2006             tcg_gen_shli_i64(xth, xth, 32);
   2007             get_cpu_vsr(t0, xA(ctx->opcode), false);
   2008             tcg_gen_shri_i64(t0, t0, 32);
   2009             tcg_gen_or_i64(xth, xth, t0);
   2010             get_cpu_vsr(xtl, xA(ctx->opcode), false);
   2011             tcg_gen_shli_i64(xtl, xtl, 32);
   2012             get_cpu_vsr(t0, xB(ctx->opcode), true);
   2013             tcg_gen_shri_i64(t0, t0, 32);
   2014             tcg_gen_or_i64(xtl, xtl, t0);
   2015             tcg_temp_free_i64(t0);
   2016             break;
   2017         }
   2018         case 2: {
   2019             get_cpu_vsr(xth, xA(ctx->opcode), false);
   2020             get_cpu_vsr(xtl, xB(ctx->opcode), true);
   2021             break;
   2022         }
   2023         case 3: {
   2024             TCGv_i64 t0 = tcg_temp_new_i64();
   2025             get_cpu_vsr(xth, xA(ctx->opcode), false);
   2026             tcg_gen_shli_i64(xth, xth, 32);
   2027             get_cpu_vsr(t0, xB(ctx->opcode), true);
   2028             tcg_gen_shri_i64(t0, t0, 32);
   2029             tcg_gen_or_i64(xth, xth, t0);
   2030             get_cpu_vsr(xtl, xB(ctx->opcode), true);
   2031             tcg_gen_shli_i64(xtl, xtl, 32);
   2032             get_cpu_vsr(t0, xB(ctx->opcode), false);
   2033             tcg_gen_shri_i64(t0, t0, 32);
   2034             tcg_gen_or_i64(xtl, xtl, t0);
   2035             tcg_temp_free_i64(t0);
   2036             break;
   2037         }
   2038     }
   2039 
   2040     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2041     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2042 
   2043     tcg_temp_free_i64(xth);
   2044     tcg_temp_free_i64(xtl);
   2045 }
   2046 
   2047 static bool do_vsx_extract_insert(DisasContext *ctx, arg_XX2_uim *a,
   2048     void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i32))
   2049 {
   2050     TCGv_i64 zero = tcg_constant_i64(0);
   2051     TCGv_ptr xt, xb;
   2052 
   2053     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2054     REQUIRE_VSX(ctx);
   2055 
   2056     /*
   2057      * uim > 15 out of bound and for
   2058      * uim > 12 handle as per hardware in helper
   2059      */
   2060     if (a->uim > 15) {
   2061         set_cpu_vsr(a->xt, zero, true);
   2062         set_cpu_vsr(a->xt, zero, false);
   2063     } else {
   2064         xt = gen_vsr_ptr(a->xt);
   2065         xb = gen_vsr_ptr(a->xb);
   2066         gen_helper(xt, xb, tcg_constant_i32(a->uim));
   2067         tcg_temp_free_ptr(xb);
   2068         tcg_temp_free_ptr(xt);
   2069     }
   2070 
   2071     return true;
   2072 }
   2073 
   2074 TRANS(XXEXTRACTUW, do_vsx_extract_insert, gen_helper_XXEXTRACTUW)
   2075 TRANS(XXINSERTW, do_vsx_extract_insert, gen_helper_XXINSERTW)
   2076 
   2077 #ifdef TARGET_PPC64
   2078 static void gen_xsxexpdp(DisasContext *ctx)
   2079 {
   2080     TCGv rt = cpu_gpr[rD(ctx->opcode)];
   2081     TCGv_i64 t0;
   2082     if (unlikely(!ctx->vsx_enabled)) {
   2083         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2084         return;
   2085     }
   2086     t0 = tcg_temp_new_i64();
   2087     get_cpu_vsr(t0, xB(ctx->opcode), true);
   2088     tcg_gen_extract_i64(rt, t0, 52, 11);
   2089     tcg_temp_free_i64(t0);
   2090 }
   2091 
   2092 static void gen_xsxexpqp(DisasContext *ctx)
   2093 {
   2094     TCGv_i64 xth;
   2095     TCGv_i64 xtl;
   2096     TCGv_i64 xbh;
   2097 
   2098     if (unlikely(!ctx->vsx_enabled)) {
   2099         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2100         return;
   2101     }
   2102     xth = tcg_temp_new_i64();
   2103     xtl = tcg_temp_new_i64();
   2104     xbh = tcg_temp_new_i64();
   2105     get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
   2106 
   2107     tcg_gen_extract_i64(xth, xbh, 48, 15);
   2108     set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
   2109     tcg_gen_movi_i64(xtl, 0);
   2110     set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
   2111 
   2112     tcg_temp_free_i64(xbh);
   2113     tcg_temp_free_i64(xth);
   2114     tcg_temp_free_i64(xtl);
   2115 }
   2116 
   2117 static void gen_xsiexpdp(DisasContext *ctx)
   2118 {
   2119     TCGv_i64 xth;
   2120     TCGv ra = cpu_gpr[rA(ctx->opcode)];
   2121     TCGv rb = cpu_gpr[rB(ctx->opcode)];
   2122     TCGv_i64 t0;
   2123 
   2124     if (unlikely(!ctx->vsx_enabled)) {
   2125         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2126         return;
   2127     }
   2128     t0 = tcg_temp_new_i64();
   2129     xth = tcg_temp_new_i64();
   2130     tcg_gen_andi_i64(xth, ra, 0x800FFFFFFFFFFFFF);
   2131     tcg_gen_andi_i64(t0, rb, 0x7FF);
   2132     tcg_gen_shli_i64(t0, t0, 52);
   2133     tcg_gen_or_i64(xth, xth, t0);
   2134     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2135     set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false);
   2136     tcg_temp_free_i64(t0);
   2137     tcg_temp_free_i64(xth);
   2138 }
   2139 
   2140 static void gen_xsiexpqp(DisasContext *ctx)
   2141 {
   2142     TCGv_i64 xth;
   2143     TCGv_i64 xtl;
   2144     TCGv_i64 xah;
   2145     TCGv_i64 xal;
   2146     TCGv_i64 xbh;
   2147     TCGv_i64 t0;
   2148 
   2149     if (unlikely(!ctx->vsx_enabled)) {
   2150         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2151         return;
   2152     }
   2153     xth = tcg_temp_new_i64();
   2154     xtl = tcg_temp_new_i64();
   2155     xah = tcg_temp_new_i64();
   2156     xal = tcg_temp_new_i64();
   2157     get_cpu_vsr(xah, rA(ctx->opcode) + 32, true);
   2158     get_cpu_vsr(xal, rA(ctx->opcode) + 32, false);
   2159     xbh = tcg_temp_new_i64();
   2160     get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
   2161     t0 = tcg_temp_new_i64();
   2162 
   2163     tcg_gen_andi_i64(xth, xah, 0x8000FFFFFFFFFFFF);
   2164     tcg_gen_andi_i64(t0, xbh, 0x7FFF);
   2165     tcg_gen_shli_i64(t0, t0, 48);
   2166     tcg_gen_or_i64(xth, xth, t0);
   2167     set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
   2168     tcg_gen_mov_i64(xtl, xal);
   2169     set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
   2170 
   2171     tcg_temp_free_i64(t0);
   2172     tcg_temp_free_i64(xth);
   2173     tcg_temp_free_i64(xtl);
   2174     tcg_temp_free_i64(xah);
   2175     tcg_temp_free_i64(xal);
   2176     tcg_temp_free_i64(xbh);
   2177 }
   2178 
   2179 static void gen_xsxsigdp(DisasContext *ctx)
   2180 {
   2181     TCGv rt = cpu_gpr[rD(ctx->opcode)];
   2182     TCGv_i64 t0, t1, zr, nan, exp;
   2183 
   2184     if (unlikely(!ctx->vsx_enabled)) {
   2185         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2186         return;
   2187     }
   2188     exp = tcg_temp_new_i64();
   2189     t0 = tcg_temp_new_i64();
   2190     t1 = tcg_temp_new_i64();
   2191     zr = tcg_const_i64(0);
   2192     nan = tcg_const_i64(2047);
   2193 
   2194     get_cpu_vsr(t1, xB(ctx->opcode), true);
   2195     tcg_gen_extract_i64(exp, t1, 52, 11);
   2196     tcg_gen_movi_i64(t0, 0x0010000000000000);
   2197     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
   2198     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
   2199     get_cpu_vsr(t1, xB(ctx->opcode), true);
   2200     tcg_gen_deposit_i64(rt, t0, t1, 0, 52);
   2201 
   2202     tcg_temp_free_i64(t0);
   2203     tcg_temp_free_i64(t1);
   2204     tcg_temp_free_i64(exp);
   2205     tcg_temp_free_i64(zr);
   2206     tcg_temp_free_i64(nan);
   2207 }
   2208 
   2209 static void gen_xsxsigqp(DisasContext *ctx)
   2210 {
   2211     TCGv_i64 t0, zr, nan, exp;
   2212     TCGv_i64 xth;
   2213     TCGv_i64 xtl;
   2214     TCGv_i64 xbh;
   2215     TCGv_i64 xbl;
   2216 
   2217     if (unlikely(!ctx->vsx_enabled)) {
   2218         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2219         return;
   2220     }
   2221     xth = tcg_temp_new_i64();
   2222     xtl = tcg_temp_new_i64();
   2223     xbh = tcg_temp_new_i64();
   2224     xbl = tcg_temp_new_i64();
   2225     get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
   2226     get_cpu_vsr(xbl, rB(ctx->opcode) + 32, false);
   2227     exp = tcg_temp_new_i64();
   2228     t0 = tcg_temp_new_i64();
   2229     zr = tcg_const_i64(0);
   2230     nan = tcg_const_i64(32767);
   2231 
   2232     tcg_gen_extract_i64(exp, xbh, 48, 15);
   2233     tcg_gen_movi_i64(t0, 0x0001000000000000);
   2234     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
   2235     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
   2236     tcg_gen_deposit_i64(xth, t0, xbh, 0, 48);
   2237     set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
   2238     tcg_gen_mov_i64(xtl, xbl);
   2239     set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
   2240 
   2241     tcg_temp_free_i64(t0);
   2242     tcg_temp_free_i64(exp);
   2243     tcg_temp_free_i64(zr);
   2244     tcg_temp_free_i64(nan);
   2245     tcg_temp_free_i64(xth);
   2246     tcg_temp_free_i64(xtl);
   2247     tcg_temp_free_i64(xbh);
   2248     tcg_temp_free_i64(xbl);
   2249 }
   2250 #endif
   2251 
   2252 static void gen_xviexpsp(DisasContext *ctx)
   2253 {
   2254     TCGv_i64 xth;
   2255     TCGv_i64 xtl;
   2256     TCGv_i64 xah;
   2257     TCGv_i64 xal;
   2258     TCGv_i64 xbh;
   2259     TCGv_i64 xbl;
   2260     TCGv_i64 t0;
   2261 
   2262     if (unlikely(!ctx->vsx_enabled)) {
   2263         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2264         return;
   2265     }
   2266     xth = tcg_temp_new_i64();
   2267     xtl = tcg_temp_new_i64();
   2268     xah = tcg_temp_new_i64();
   2269     xal = tcg_temp_new_i64();
   2270     xbh = tcg_temp_new_i64();
   2271     xbl = tcg_temp_new_i64();
   2272     get_cpu_vsr(xah, xA(ctx->opcode), true);
   2273     get_cpu_vsr(xal, xA(ctx->opcode), false);
   2274     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   2275     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   2276     t0 = tcg_temp_new_i64();
   2277 
   2278     tcg_gen_andi_i64(xth, xah, 0x807FFFFF807FFFFF);
   2279     tcg_gen_andi_i64(t0, xbh, 0xFF000000FF);
   2280     tcg_gen_shli_i64(t0, t0, 23);
   2281     tcg_gen_or_i64(xth, xth, t0);
   2282     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2283     tcg_gen_andi_i64(xtl, xal, 0x807FFFFF807FFFFF);
   2284     tcg_gen_andi_i64(t0, xbl, 0xFF000000FF);
   2285     tcg_gen_shli_i64(t0, t0, 23);
   2286     tcg_gen_or_i64(xtl, xtl, t0);
   2287     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2288 
   2289     tcg_temp_free_i64(t0);
   2290     tcg_temp_free_i64(xth);
   2291     tcg_temp_free_i64(xtl);
   2292     tcg_temp_free_i64(xah);
   2293     tcg_temp_free_i64(xal);
   2294     tcg_temp_free_i64(xbh);
   2295     tcg_temp_free_i64(xbl);
   2296 }
   2297 
   2298 static void gen_xviexpdp(DisasContext *ctx)
   2299 {
   2300     TCGv_i64 xth;
   2301     TCGv_i64 xtl;
   2302     TCGv_i64 xah;
   2303     TCGv_i64 xal;
   2304     TCGv_i64 xbh;
   2305     TCGv_i64 xbl;
   2306 
   2307     if (unlikely(!ctx->vsx_enabled)) {
   2308         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2309         return;
   2310     }
   2311     xth = tcg_temp_new_i64();
   2312     xtl = tcg_temp_new_i64();
   2313     xah = tcg_temp_new_i64();
   2314     xal = tcg_temp_new_i64();
   2315     xbh = tcg_temp_new_i64();
   2316     xbl = tcg_temp_new_i64();
   2317     get_cpu_vsr(xah, xA(ctx->opcode), true);
   2318     get_cpu_vsr(xal, xA(ctx->opcode), false);
   2319     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   2320     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   2321 
   2322     tcg_gen_deposit_i64(xth, xah, xbh, 52, 11);
   2323     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2324 
   2325     tcg_gen_deposit_i64(xtl, xal, xbl, 52, 11);
   2326     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2327 
   2328     tcg_temp_free_i64(xth);
   2329     tcg_temp_free_i64(xtl);
   2330     tcg_temp_free_i64(xah);
   2331     tcg_temp_free_i64(xal);
   2332     tcg_temp_free_i64(xbh);
   2333     tcg_temp_free_i64(xbl);
   2334 }
   2335 
   2336 static void gen_xvxexpsp(DisasContext *ctx)
   2337 {
   2338     TCGv_i64 xth;
   2339     TCGv_i64 xtl;
   2340     TCGv_i64 xbh;
   2341     TCGv_i64 xbl;
   2342 
   2343     if (unlikely(!ctx->vsx_enabled)) {
   2344         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2345         return;
   2346     }
   2347     xth = tcg_temp_new_i64();
   2348     xtl = tcg_temp_new_i64();
   2349     xbh = tcg_temp_new_i64();
   2350     xbl = tcg_temp_new_i64();
   2351     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   2352     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   2353 
   2354     tcg_gen_shri_i64(xth, xbh, 23);
   2355     tcg_gen_andi_i64(xth, xth, 0xFF000000FF);
   2356     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2357     tcg_gen_shri_i64(xtl, xbl, 23);
   2358     tcg_gen_andi_i64(xtl, xtl, 0xFF000000FF);
   2359     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2360 
   2361     tcg_temp_free_i64(xth);
   2362     tcg_temp_free_i64(xtl);
   2363     tcg_temp_free_i64(xbh);
   2364     tcg_temp_free_i64(xbl);
   2365 }
   2366 
   2367 static void gen_xvxexpdp(DisasContext *ctx)
   2368 {
   2369     TCGv_i64 xth;
   2370     TCGv_i64 xtl;
   2371     TCGv_i64 xbh;
   2372     TCGv_i64 xbl;
   2373 
   2374     if (unlikely(!ctx->vsx_enabled)) {
   2375         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2376         return;
   2377     }
   2378     xth = tcg_temp_new_i64();
   2379     xtl = tcg_temp_new_i64();
   2380     xbh = tcg_temp_new_i64();
   2381     xbl = tcg_temp_new_i64();
   2382     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   2383     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   2384 
   2385     tcg_gen_extract_i64(xth, xbh, 52, 11);
   2386     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2387     tcg_gen_extract_i64(xtl, xbl, 52, 11);
   2388     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2389 
   2390     tcg_temp_free_i64(xth);
   2391     tcg_temp_free_i64(xtl);
   2392     tcg_temp_free_i64(xbh);
   2393     tcg_temp_free_i64(xbl);
   2394 }
   2395 
   2396 static bool trans_XVXSIGSP(DisasContext *ctx, arg_XX2 *a)
   2397 {
   2398     TCGv_ptr t, b;
   2399 
   2400     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2401     REQUIRE_VSX(ctx);
   2402 
   2403     t = gen_vsr_ptr(a->xt);
   2404     b = gen_vsr_ptr(a->xb);
   2405 
   2406     gen_helper_XVXSIGSP(t, b);
   2407 
   2408     tcg_temp_free_ptr(t);
   2409     tcg_temp_free_ptr(b);
   2410 
   2411     return true;
   2412 }
   2413 
   2414 static void gen_xvxsigdp(DisasContext *ctx)
   2415 {
   2416     TCGv_i64 xth;
   2417     TCGv_i64 xtl;
   2418     TCGv_i64 xbh;
   2419     TCGv_i64 xbl;
   2420     TCGv_i64 t0, zr, nan, exp;
   2421 
   2422     if (unlikely(!ctx->vsx_enabled)) {
   2423         gen_exception(ctx, POWERPC_EXCP_VSXU);
   2424         return;
   2425     }
   2426     xth = tcg_temp_new_i64();
   2427     xtl = tcg_temp_new_i64();
   2428     xbh = tcg_temp_new_i64();
   2429     xbl = tcg_temp_new_i64();
   2430     get_cpu_vsr(xbh, xB(ctx->opcode), true);
   2431     get_cpu_vsr(xbl, xB(ctx->opcode), false);
   2432     exp = tcg_temp_new_i64();
   2433     t0 = tcg_temp_new_i64();
   2434     zr = tcg_const_i64(0);
   2435     nan = tcg_const_i64(2047);
   2436 
   2437     tcg_gen_extract_i64(exp, xbh, 52, 11);
   2438     tcg_gen_movi_i64(t0, 0x0010000000000000);
   2439     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
   2440     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
   2441     tcg_gen_deposit_i64(xth, t0, xbh, 0, 52);
   2442     set_cpu_vsr(xT(ctx->opcode), xth, true);
   2443 
   2444     tcg_gen_extract_i64(exp, xbl, 52, 11);
   2445     tcg_gen_movi_i64(t0, 0x0010000000000000);
   2446     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
   2447     tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
   2448     tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52);
   2449     set_cpu_vsr(xT(ctx->opcode), xtl, false);
   2450 
   2451     tcg_temp_free_i64(t0);
   2452     tcg_temp_free_i64(exp);
   2453     tcg_temp_free_i64(zr);
   2454     tcg_temp_free_i64(nan);
   2455     tcg_temp_free_i64(xth);
   2456     tcg_temp_free_i64(xtl);
   2457     tcg_temp_free_i64(xbh);
   2458     tcg_temp_free_i64(xbl);
   2459 }
   2460 
   2461 static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
   2462                      int rt, bool store, bool paired)
   2463 {
   2464     TCGv ea;
   2465     TCGv_i64 xt;
   2466     MemOp mop;
   2467     int rt1, rt2;
   2468 
   2469     xt = tcg_temp_new_i64();
   2470 
   2471     mop = DEF_MEMOP(MO_UQ);
   2472 
   2473     gen_set_access_type(ctx, ACCESS_INT);
   2474     ea = do_ea_calc(ctx, ra, displ);
   2475 
   2476     if (paired && ctx->le_mode) {
   2477         rt1 = rt + 1;
   2478         rt2 = rt;
   2479     } else {
   2480         rt1 = rt;
   2481         rt2 = rt + 1;
   2482     }
   2483 
   2484     if (store) {
   2485         get_cpu_vsr(xt, rt1, !ctx->le_mode);
   2486         tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2487         gen_addr_add(ctx, ea, ea, 8);
   2488         get_cpu_vsr(xt, rt1, ctx->le_mode);
   2489         tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2490         if (paired) {
   2491             gen_addr_add(ctx, ea, ea, 8);
   2492             get_cpu_vsr(xt, rt2, !ctx->le_mode);
   2493             tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2494             gen_addr_add(ctx, ea, ea, 8);
   2495             get_cpu_vsr(xt, rt2, ctx->le_mode);
   2496             tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2497         }
   2498     } else {
   2499         tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2500         set_cpu_vsr(rt1, xt, !ctx->le_mode);
   2501         gen_addr_add(ctx, ea, ea, 8);
   2502         tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2503         set_cpu_vsr(rt1, xt, ctx->le_mode);
   2504         if (paired) {
   2505             gen_addr_add(ctx, ea, ea, 8);
   2506             tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2507             set_cpu_vsr(rt2, xt, !ctx->le_mode);
   2508             gen_addr_add(ctx, ea, ea, 8);
   2509             tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2510             set_cpu_vsr(rt2, xt, ctx->le_mode);
   2511         }
   2512     }
   2513 
   2514     tcg_temp_free(ea);
   2515     tcg_temp_free_i64(xt);
   2516     return true;
   2517 }
   2518 
   2519 static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired)
   2520 {
   2521     if (paired || a->rt >= 32) {
   2522         REQUIRE_VSX(ctx);
   2523     } else {
   2524         REQUIRE_VECTOR(ctx);
   2525     }
   2526 
   2527     return do_lstxv(ctx, a->ra, tcg_constant_tl(a->si), a->rt, store, paired);
   2528 }
   2529 
   2530 static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a,
   2531                            bool store, bool paired)
   2532 {
   2533     arg_D d;
   2534     REQUIRE_VSX(ctx);
   2535 
   2536     if (!resolve_PLS_D(ctx, &d, a)) {
   2537         return true;
   2538     }
   2539 
   2540     return do_lstxv(ctx, d.ra, tcg_constant_tl(d.si), d.rt, store, paired);
   2541 }
   2542 
   2543 static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired)
   2544 {
   2545     if (paired || a->rt >= 32) {
   2546         REQUIRE_VSX(ctx);
   2547     } else {
   2548         REQUIRE_VECTOR(ctx);
   2549     }
   2550 
   2551     return do_lstxv(ctx, a->ra, cpu_gpr[a->rb], a->rt, store, paired);
   2552 }
   2553 
   2554 static bool do_lstxsd(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
   2555 {
   2556     TCGv ea;
   2557     TCGv_i64 xt;
   2558     MemOp mop;
   2559 
   2560     if (store) {
   2561         REQUIRE_VECTOR(ctx);
   2562     } else {
   2563         REQUIRE_VSX(ctx);
   2564     }
   2565 
   2566     xt = tcg_temp_new_i64();
   2567     mop = DEF_MEMOP(MO_UQ);
   2568 
   2569     gen_set_access_type(ctx, ACCESS_INT);
   2570     ea = do_ea_calc(ctx, ra, displ);
   2571 
   2572     if (store) {
   2573         get_cpu_vsr(xt, rt + 32, true);
   2574         tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2575     } else {
   2576         tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2577         set_cpu_vsr(rt + 32, xt, true);
   2578         set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
   2579     }
   2580 
   2581     tcg_temp_free(ea);
   2582     tcg_temp_free_i64(xt);
   2583 
   2584     return true;
   2585 }
   2586 
   2587 static bool do_lstxsd_DS(DisasContext *ctx, arg_D *a, bool store)
   2588 {
   2589     return do_lstxsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
   2590 }
   2591 
   2592 static bool do_plstxsd_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
   2593 {
   2594     arg_D d;
   2595 
   2596     if (!resolve_PLS_D(ctx, &d, a)) {
   2597         return true;
   2598     }
   2599 
   2600     return do_lstxsd(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
   2601 }
   2602 
   2603 static bool do_lstxssp(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
   2604 {
   2605     TCGv ea;
   2606     TCGv_i64 xt;
   2607 
   2608     REQUIRE_VECTOR(ctx);
   2609 
   2610     xt = tcg_temp_new_i64();
   2611 
   2612     gen_set_access_type(ctx, ACCESS_INT);
   2613     ea = do_ea_calc(ctx, ra, displ);
   2614 
   2615     if (store) {
   2616         get_cpu_vsr(xt, rt + 32, true);
   2617         gen_qemu_st32fs(ctx, xt, ea);
   2618     } else {
   2619         gen_qemu_ld32fs(ctx, xt, ea);
   2620         set_cpu_vsr(rt + 32, xt, true);
   2621         set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
   2622     }
   2623 
   2624     tcg_temp_free(ea);
   2625     tcg_temp_free_i64(xt);
   2626 
   2627     return true;
   2628 }
   2629 
   2630 static bool do_lstxssp_DS(DisasContext *ctx, arg_D *a, bool store)
   2631 {
   2632     return do_lstxssp(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
   2633 }
   2634 
   2635 static bool do_plstxssp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
   2636 {
   2637     arg_D d;
   2638 
   2639     if (!resolve_PLS_D(ctx, &d, a)) {
   2640         return true;
   2641     }
   2642 
   2643     return do_lstxssp(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
   2644 }
   2645 
   2646 TRANS_FLAGS2(ISA300, LXSD, do_lstxsd_DS, false)
   2647 TRANS_FLAGS2(ISA300, STXSD, do_lstxsd_DS, true)
   2648 TRANS_FLAGS2(ISA300, LXSSP, do_lstxssp_DS, false)
   2649 TRANS_FLAGS2(ISA300, STXSSP, do_lstxssp_DS, true)
   2650 TRANS_FLAGS2(ISA300, STXV, do_lstxv_D, true, false)
   2651 TRANS_FLAGS2(ISA300, LXV, do_lstxv_D, false, false)
   2652 TRANS_FLAGS2(ISA310, STXVP, do_lstxv_D, true, true)
   2653 TRANS_FLAGS2(ISA310, LXVP, do_lstxv_D, false, true)
   2654 TRANS_FLAGS2(ISA300, STXVX, do_lstxv_X, true, false)
   2655 TRANS_FLAGS2(ISA300, LXVX, do_lstxv_X, false, false)
   2656 TRANS_FLAGS2(ISA310, STXVPX, do_lstxv_X, true, true)
   2657 TRANS_FLAGS2(ISA310, LXVPX, do_lstxv_X, false, true)
   2658 TRANS64_FLAGS2(ISA310, PLXSD, do_plstxsd_PLS_D, false)
   2659 TRANS64_FLAGS2(ISA310, PSTXSD, do_plstxsd_PLS_D, true)
   2660 TRANS64_FLAGS2(ISA310, PLXSSP, do_plstxssp_PLS_D, false)
   2661 TRANS64_FLAGS2(ISA310, PSTXSSP, do_plstxssp_PLS_D, true)
   2662 TRANS64_FLAGS2(ISA310, PSTXV, do_lstxv_PLS_D, true, false)
   2663 TRANS64_FLAGS2(ISA310, PLXV, do_lstxv_PLS_D, false, false)
   2664 TRANS64_FLAGS2(ISA310, PSTXVP, do_lstxv_PLS_D, true, true)
   2665 TRANS64_FLAGS2(ISA310, PLXVP, do_lstxv_PLS_D, false, true)
   2666 
   2667 static bool do_lstrm(DisasContext *ctx, arg_X *a, MemOp mop, bool store)
   2668 {
   2669     TCGv ea;
   2670     TCGv_i64 xt;
   2671 
   2672     REQUIRE_VSX(ctx);
   2673 
   2674     xt = tcg_temp_new_i64();
   2675 
   2676     gen_set_access_type(ctx, ACCESS_INT);
   2677     ea = do_ea_calc(ctx, a->ra , cpu_gpr[a->rb]);
   2678 
   2679     if (store) {
   2680         get_cpu_vsr(xt, a->rt, false);
   2681         tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
   2682     } else {
   2683         tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
   2684         set_cpu_vsr(a->rt, xt, false);
   2685         set_cpu_vsr(a->rt, tcg_constant_i64(0), true);
   2686     }
   2687 
   2688     tcg_temp_free(ea);
   2689     tcg_temp_free_i64(xt);
   2690     return true;
   2691 }
   2692 
   2693 TRANS_FLAGS2(ISA310, LXVRBX, do_lstrm, DEF_MEMOP(MO_UB), false)
   2694 TRANS_FLAGS2(ISA310, LXVRHX, do_lstrm, DEF_MEMOP(MO_UW), false)
   2695 TRANS_FLAGS2(ISA310, LXVRWX, do_lstrm, DEF_MEMOP(MO_UL), false)
   2696 TRANS_FLAGS2(ISA310, LXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), false)
   2697 TRANS_FLAGS2(ISA310, STXVRBX, do_lstrm, DEF_MEMOP(MO_UB), true)
   2698 TRANS_FLAGS2(ISA310, STXVRHX, do_lstrm, DEF_MEMOP(MO_UW), true)
   2699 TRANS_FLAGS2(ISA310, STXVRWX, do_lstrm, DEF_MEMOP(MO_UL), true)
   2700 TRANS_FLAGS2(ISA310, STXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), true)
   2701 
   2702 static void gen_xxeval_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c,
   2703                            int64_t imm)
   2704 {
   2705     /*
   2706      * Instead of processing imm bit-by-bit, we'll skip the computation of
   2707      * conjunctions whose corresponding bit is unset.
   2708      */
   2709     int bit;
   2710     TCGv_i64 conj, disj;
   2711 
   2712     conj = tcg_temp_new_i64();
   2713     disj = tcg_const_i64(0);
   2714 
   2715     /* Iterate over set bits from the least to the most significant bit */
   2716     while (imm) {
   2717         /*
   2718          * Get the next bit to be processed with ctz64. Invert the result of
   2719          * ctz64 to match the indexing used by PowerISA.
   2720          */
   2721         bit = 7 - ctz64(imm);
   2722         if (bit & 0x4) {
   2723             tcg_gen_mov_i64(conj, a);
   2724         } else {
   2725             tcg_gen_not_i64(conj, a);
   2726         }
   2727         if (bit & 0x2) {
   2728             tcg_gen_and_i64(conj, conj, b);
   2729         } else {
   2730             tcg_gen_andc_i64(conj, conj, b);
   2731         }
   2732         if (bit & 0x1) {
   2733             tcg_gen_and_i64(conj, conj, c);
   2734         } else {
   2735             tcg_gen_andc_i64(conj, conj, c);
   2736         }
   2737         tcg_gen_or_i64(disj, disj, conj);
   2738 
   2739         /* Unset the least significant bit that is set */
   2740         imm &= imm - 1;
   2741     }
   2742 
   2743     tcg_gen_mov_i64(t, disj);
   2744 
   2745     tcg_temp_free_i64(conj);
   2746     tcg_temp_free_i64(disj);
   2747 }
   2748 
   2749 static void gen_xxeval_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
   2750                            TCGv_vec c, int64_t imm)
   2751 {
   2752     /*
   2753      * Instead of processing imm bit-by-bit, we'll skip the computation of
   2754      * conjunctions whose corresponding bit is unset.
   2755      */
   2756     int bit;
   2757     TCGv_vec disj, conj;
   2758 
   2759     disj = tcg_const_zeros_vec_matching(t);
   2760     conj = tcg_temp_new_vec_matching(t);
   2761 
   2762     /* Iterate over set bits from the least to the most significant bit */
   2763     while (imm) {
   2764         /*
   2765          * Get the next bit to be processed with ctz64. Invert the result of
   2766          * ctz64 to match the indexing used by PowerISA.
   2767          */
   2768         bit = 7 - ctz64(imm);
   2769         if (bit & 0x4) {
   2770             tcg_gen_mov_vec(conj, a);
   2771         } else {
   2772             tcg_gen_not_vec(vece, conj, a);
   2773         }
   2774         if (bit & 0x2) {
   2775             tcg_gen_and_vec(vece, conj, conj, b);
   2776         } else {
   2777             tcg_gen_andc_vec(vece, conj, conj, b);
   2778         }
   2779         if (bit & 0x1) {
   2780             tcg_gen_and_vec(vece, conj, conj, c);
   2781         } else {
   2782             tcg_gen_andc_vec(vece, conj, conj, c);
   2783         }
   2784         tcg_gen_or_vec(vece, disj, disj, conj);
   2785 
   2786         /* Unset the least significant bit that is set */
   2787         imm &= imm - 1;
   2788     }
   2789 
   2790     tcg_gen_mov_vec(t, disj);
   2791 
   2792     tcg_temp_free_vec(disj);
   2793     tcg_temp_free_vec(conj);
   2794 }
   2795 
   2796 static bool trans_XXEVAL(DisasContext *ctx, arg_8RR_XX4_imm *a)
   2797 {
   2798     static const TCGOpcode vecop_list[] = {
   2799         INDEX_op_andc_vec, 0
   2800     };
   2801     static const GVecGen4i op = {
   2802         .fniv = gen_xxeval_vec,
   2803         .fno = gen_helper_XXEVAL,
   2804         .fni8 = gen_xxeval_i64,
   2805         .opt_opc = vecop_list,
   2806         .vece = MO_64
   2807     };
   2808     int xt = vsr_full_offset(a->xt), xa = vsr_full_offset(a->xa),
   2809         xb = vsr_full_offset(a->xb), xc = vsr_full_offset(a->xc);
   2810 
   2811     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   2812     REQUIRE_VSX(ctx);
   2813 
   2814     /* Equivalent functions that can be implemented with a single gen_gvec */
   2815     switch (a->imm) {
   2816     case 0b00000000: /* true */
   2817         set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
   2818         set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
   2819         break;
   2820     case 0b00000011: /* and(B,A) */
   2821         tcg_gen_gvec_and(MO_64, xt, xb, xa, 16, 16);
   2822         break;
   2823     case 0b00000101: /* and(C,A) */
   2824         tcg_gen_gvec_and(MO_64, xt, xc, xa, 16, 16);
   2825         break;
   2826     case 0b00001111: /* A */
   2827         tcg_gen_gvec_mov(MO_64, xt, xa, 16, 16);
   2828         break;
   2829     case 0b00010001: /* and(C,B) */
   2830         tcg_gen_gvec_and(MO_64, xt, xc, xb, 16, 16);
   2831         break;
   2832     case 0b00011011: /* C?B:A */
   2833         tcg_gen_gvec_bitsel(MO_64, xt, xc, xb, xa, 16, 16);
   2834         break;
   2835     case 0b00011101: /* B?C:A */
   2836         tcg_gen_gvec_bitsel(MO_64, xt, xb, xc, xa, 16, 16);
   2837         break;
   2838     case 0b00100111: /* C?A:B */
   2839         tcg_gen_gvec_bitsel(MO_64, xt, xc, xa, xb, 16, 16);
   2840         break;
   2841     case 0b00110011: /* B */
   2842         tcg_gen_gvec_mov(MO_64, xt, xb, 16, 16);
   2843         break;
   2844     case 0b00110101: /* A?C:B */
   2845         tcg_gen_gvec_bitsel(MO_64, xt, xa, xc, xb, 16, 16);
   2846         break;
   2847     case 0b00111100: /* xor(B,A) */
   2848         tcg_gen_gvec_xor(MO_64, xt, xb, xa, 16, 16);
   2849         break;
   2850     case 0b00111111: /* or(B,A) */
   2851         tcg_gen_gvec_or(MO_64, xt, xb, xa, 16, 16);
   2852         break;
   2853     case 0b01000111: /* B?A:C */
   2854         tcg_gen_gvec_bitsel(MO_64, xt, xb, xa, xc, 16, 16);
   2855         break;
   2856     case 0b01010011: /* A?B:C */
   2857         tcg_gen_gvec_bitsel(MO_64, xt, xa, xb, xc, 16, 16);
   2858         break;
   2859     case 0b01010101: /* C */
   2860         tcg_gen_gvec_mov(MO_64, xt, xc, 16, 16);
   2861         break;
   2862     case 0b01011010: /* xor(C,A) */
   2863         tcg_gen_gvec_xor(MO_64, xt, xc, xa, 16, 16);
   2864         break;
   2865     case 0b01011111: /* or(C,A) */
   2866         tcg_gen_gvec_or(MO_64, xt, xc, xa, 16, 16);
   2867         break;
   2868     case 0b01100110: /* xor(C,B) */
   2869         tcg_gen_gvec_xor(MO_64, xt, xc, xb, 16, 16);
   2870         break;
   2871     case 0b01110111: /* or(C,B) */
   2872         tcg_gen_gvec_or(MO_64, xt, xc, xb, 16, 16);
   2873         break;
   2874     case 0b10001000: /* nor(C,B) */
   2875         tcg_gen_gvec_nor(MO_64, xt, xc, xb, 16, 16);
   2876         break;
   2877     case 0b10011001: /* eqv(C,B) */
   2878         tcg_gen_gvec_eqv(MO_64, xt, xc, xb, 16, 16);
   2879         break;
   2880     case 0b10100000: /* nor(C,A) */
   2881         tcg_gen_gvec_nor(MO_64, xt, xc, xa, 16, 16);
   2882         break;
   2883     case 0b10100101: /* eqv(C,A) */
   2884         tcg_gen_gvec_eqv(MO_64, xt, xc, xa, 16, 16);
   2885         break;
   2886     case 0b10101010: /* not(C) */
   2887         tcg_gen_gvec_not(MO_64, xt, xc, 16, 16);
   2888         break;
   2889     case 0b11000000: /* nor(B,A) */
   2890         tcg_gen_gvec_nor(MO_64, xt,  xb, xa, 16, 16);
   2891         break;
   2892     case 0b11000011: /* eqv(B,A) */
   2893         tcg_gen_gvec_eqv(MO_64, xt,  xb, xa, 16, 16);
   2894         break;
   2895     case 0b11001100: /* not(B) */
   2896         tcg_gen_gvec_not(MO_64, xt, xb, 16, 16);
   2897         break;
   2898     case 0b11101110: /* nand(C,B) */
   2899         tcg_gen_gvec_nand(MO_64, xt, xc, xb, 16, 16);
   2900         break;
   2901     case 0b11110000: /* not(A) */
   2902         tcg_gen_gvec_not(MO_64, xt, xa, 16, 16);
   2903         break;
   2904     case 0b11111010: /* nand(C,A) */
   2905         tcg_gen_gvec_nand(MO_64, xt, xc, xa, 16, 16);
   2906         break;
   2907     case 0b11111100: /* nand(B,A) */
   2908         tcg_gen_gvec_nand(MO_64, xt, xb, xa, 16, 16);
   2909         break;
   2910     case 0b11111111: /* true */
   2911         set_cpu_vsr(a->xt, tcg_constant_i64(-1), true);
   2912         set_cpu_vsr(a->xt, tcg_constant_i64(-1), false);
   2913         break;
   2914     default:
   2915         /* Fallback to compute all conjunctions/disjunctions */
   2916         tcg_gen_gvec_4i(xt, xa, xb, xc, 16, 16, a->imm, &op);
   2917     }
   2918 
   2919     return true;
   2920 }
   2921 
   2922 static void gen_xxblendv_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
   2923                              TCGv_vec c)
   2924 {
   2925     TCGv_vec tmp = tcg_temp_new_vec_matching(c);
   2926     tcg_gen_sari_vec(vece, tmp, c, (8 << vece) - 1);
   2927     tcg_gen_bitsel_vec(vece, t, tmp, b, a);
   2928     tcg_temp_free_vec(tmp);
   2929 }
   2930 
   2931 static bool do_xxblendv(DisasContext *ctx, arg_8RR_XX4 *a, unsigned vece)
   2932 {
   2933     static const TCGOpcode vecop_list[] = {
   2934         INDEX_op_sari_vec, 0
   2935     };
   2936     static const GVecGen4 ops[4] = {
   2937         {
   2938             .fniv = gen_xxblendv_vec,
   2939             .fno = gen_helper_XXBLENDVB,
   2940             .opt_opc = vecop_list,
   2941             .vece = MO_8
   2942         },
   2943         {
   2944             .fniv = gen_xxblendv_vec,
   2945             .fno = gen_helper_XXBLENDVH,
   2946             .opt_opc = vecop_list,
   2947             .vece = MO_16
   2948         },
   2949         {
   2950             .fniv = gen_xxblendv_vec,
   2951             .fno = gen_helper_XXBLENDVW,
   2952             .opt_opc = vecop_list,
   2953             .vece = MO_32
   2954         },
   2955         {
   2956             .fniv = gen_xxblendv_vec,
   2957             .fno = gen_helper_XXBLENDVD,
   2958             .opt_opc = vecop_list,
   2959             .vece = MO_64
   2960         }
   2961     };
   2962 
   2963     REQUIRE_VSX(ctx);
   2964 
   2965     tcg_gen_gvec_4(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
   2966                    vsr_full_offset(a->xb), vsr_full_offset(a->xc),
   2967                    16, 16, &ops[vece]);
   2968 
   2969     return true;
   2970 }
   2971 
   2972 TRANS(XXBLENDVB, do_xxblendv, MO_8)
   2973 TRANS(XXBLENDVH, do_xxblendv, MO_16)
   2974 TRANS(XXBLENDVW, do_xxblendv, MO_32)
   2975 TRANS(XXBLENDVD, do_xxblendv, MO_64)
   2976 
   2977 static bool do_helper_XX3(DisasContext *ctx, arg_XX3 *a,
   2978     void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   2979 {
   2980     TCGv_ptr xt, xa, xb;
   2981 
   2982     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
   2983     REQUIRE_VSX(ctx);
   2984 
   2985     xt = gen_vsr_ptr(a->xt);
   2986     xa = gen_vsr_ptr(a->xa);
   2987     xb = gen_vsr_ptr(a->xb);
   2988 
   2989     helper(cpu_env, xt, xa, xb);
   2990 
   2991     tcg_temp_free_ptr(xt);
   2992     tcg_temp_free_ptr(xa);
   2993     tcg_temp_free_ptr(xb);
   2994 
   2995     return true;
   2996 }
   2997 
   2998 TRANS(XSCMPEQDP, do_helper_XX3, gen_helper_XSCMPEQDP)
   2999 TRANS(XSCMPGEDP, do_helper_XX3, gen_helper_XSCMPGEDP)
   3000 TRANS(XSCMPGTDP, do_helper_XX3, gen_helper_XSCMPGTDP)
   3001 TRANS(XSMAXCDP, do_helper_XX3, gen_helper_XSMAXCDP)
   3002 TRANS(XSMINCDP, do_helper_XX3, gen_helper_XSMINCDP)
   3003 TRANS(XSMAXJDP, do_helper_XX3, gen_helper_XSMAXJDP)
   3004 TRANS(XSMINJDP, do_helper_XX3, gen_helper_XSMINJDP)
   3005 
   3006 static bool do_helper_X(arg_X *a,
   3007     void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   3008 {
   3009     TCGv_ptr rt, ra, rb;
   3010 
   3011     rt = gen_avr_ptr(a->rt);
   3012     ra = gen_avr_ptr(a->ra);
   3013     rb = gen_avr_ptr(a->rb);
   3014 
   3015     helper(cpu_env, rt, ra, rb);
   3016 
   3017     tcg_temp_free_ptr(rt);
   3018     tcg_temp_free_ptr(ra);
   3019     tcg_temp_free_ptr(rb);
   3020 
   3021     return true;
   3022 }
   3023 
   3024 static bool do_xscmpqp(DisasContext *ctx, arg_X *a,
   3025     void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
   3026 {
   3027     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3028     REQUIRE_VSX(ctx);
   3029 
   3030     return do_helper_X(a, helper);
   3031 }
   3032 
   3033 TRANS(XSCMPEQQP, do_xscmpqp, gen_helper_XSCMPEQQP)
   3034 TRANS(XSCMPGEQP, do_xscmpqp, gen_helper_XSCMPGEQP)
   3035 TRANS(XSCMPGTQP, do_xscmpqp, gen_helper_XSCMPGTQP)
   3036 TRANS(XSMAXCQP, do_xscmpqp, gen_helper_XSMAXCQP)
   3037 TRANS(XSMINCQP, do_xscmpqp, gen_helper_XSMINCQP)
   3038 
   3039 static bool trans_XVCVSPBF16(DisasContext *ctx, arg_XX2 *a)
   3040 {
   3041     TCGv_ptr xt, xb;
   3042 
   3043     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3044     REQUIRE_VSX(ctx);
   3045 
   3046     xt = gen_vsr_ptr(a->xt);
   3047     xb = gen_vsr_ptr(a->xb);
   3048 
   3049     gen_helper_XVCVSPBF16(cpu_env, xt, xb);
   3050 
   3051     tcg_temp_free_ptr(xt);
   3052     tcg_temp_free_ptr(xb);
   3053 
   3054     return true;
   3055 }
   3056 
   3057 static bool trans_XVCVBF16SPN(DisasContext *ctx, arg_XX2 *a)
   3058 {
   3059     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3060     REQUIRE_VSX(ctx);
   3061 
   3062     tcg_gen_gvec_shli(MO_32, vsr_full_offset(a->xt), vsr_full_offset(a->xb),
   3063                       16, 16, 16);
   3064 
   3065     return true;
   3066 }
   3067 
   3068     /*
   3069      *  The PowerISA 3.1 mentions that for the current version of the
   3070      *  architecture, "the hardware implementation provides the effect of
   3071      *  ACC[i] and VSRs 4*i to 4*i + 3 logically containing the same data"
   3072      *  and "The Accumulators introduce no new logical state at this time"
   3073      *  (page 501). For now it seems unnecessary to create new structures,
   3074      *  so ACC[i] is the same as VSRs 4*i to 4*i+3 and therefore
   3075      *  move to and from accumulators are no-ops.
   3076      */
   3077 static bool trans_XXMFACC(DisasContext *ctx, arg_X_a *a)
   3078 {
   3079     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3080     REQUIRE_VSX(ctx);
   3081     return true;
   3082 }
   3083 
   3084 static bool trans_XXMTACC(DisasContext *ctx, arg_X_a *a)
   3085 {
   3086     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3087     REQUIRE_VSX(ctx);
   3088     return true;
   3089 }
   3090 
   3091 static bool trans_XXSETACCZ(DisasContext *ctx, arg_X_a *a)
   3092 {
   3093     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3094     REQUIRE_VSX(ctx);
   3095     tcg_gen_gvec_dup_imm(MO_64, acc_full_offset(a->ra), 64, 64, 0);
   3096     return true;
   3097 }
   3098 
   3099 static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
   3100     void (*helper)(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32))
   3101 {
   3102     uint32_t mask;
   3103     TCGv_ptr xt, xa, xb;
   3104     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
   3105     REQUIRE_VSX(ctx);
   3106     if (unlikely((a->xa / 4 == a->xt) || (a->xb / 4 == a->xt))) {
   3107         gen_invalid(ctx);
   3108         return true;
   3109     }
   3110 
   3111     xt = gen_acc_ptr(a->xt);
   3112     xa = gen_vsr_ptr(a->xa);
   3113     xb = gen_vsr_ptr(a->xb);
   3114 
   3115     mask = ger_pack_masks(a->pmsk, a->ymsk, a->xmsk);
   3116     helper(cpu_env, xa, xb, xt, tcg_constant_i32(mask));
   3117     tcg_temp_free_ptr(xt);
   3118     tcg_temp_free_ptr(xa);
   3119     tcg_temp_free_ptr(xb);
   3120     return true;
   3121 }
   3122 
   3123 TRANS(XVI4GER8, do_ger, gen_helper_XVI4GER8)
   3124 TRANS(XVI4GER8PP, do_ger,  gen_helper_XVI4GER8PP)
   3125 TRANS(XVI8GER4, do_ger, gen_helper_XVI8GER4)
   3126 TRANS(XVI8GER4PP, do_ger,  gen_helper_XVI8GER4PP)
   3127 TRANS(XVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
   3128 TRANS(XVI16GER2, do_ger, gen_helper_XVI16GER2)
   3129 TRANS(XVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
   3130 TRANS(XVI16GER2S, do_ger, gen_helper_XVI16GER2S)
   3131 TRANS(XVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
   3132 
   3133 TRANS64(PMXVI4GER8, do_ger, gen_helper_XVI4GER8)
   3134 TRANS64(PMXVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
   3135 TRANS64(PMXVI8GER4, do_ger, gen_helper_XVI8GER4)
   3136 TRANS64(PMXVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
   3137 TRANS64(PMXVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
   3138 TRANS64(PMXVI16GER2, do_ger, gen_helper_XVI16GER2)
   3139 TRANS64(PMXVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
   3140 TRANS64(PMXVI16GER2S, do_ger, gen_helper_XVI16GER2S)
   3141 TRANS64(PMXVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
   3142 
   3143 TRANS(XVBF16GER2, do_ger, gen_helper_XVBF16GER2)
   3144 TRANS(XVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
   3145 TRANS(XVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
   3146 TRANS(XVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
   3147 TRANS(XVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
   3148 
   3149 TRANS(XVF16GER2, do_ger, gen_helper_XVF16GER2)
   3150 TRANS(XVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
   3151 TRANS(XVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
   3152 TRANS(XVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
   3153 TRANS(XVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
   3154 
   3155 TRANS(XVF32GER, do_ger, gen_helper_XVF32GER)
   3156 TRANS(XVF32GERPP, do_ger, gen_helper_XVF32GERPP)
   3157 TRANS(XVF32GERPN, do_ger, gen_helper_XVF32GERPN)
   3158 TRANS(XVF32GERNP, do_ger, gen_helper_XVF32GERNP)
   3159 TRANS(XVF32GERNN, do_ger, gen_helper_XVF32GERNN)
   3160 
   3161 TRANS(XVF64GER, do_ger, gen_helper_XVF64GER)
   3162 TRANS(XVF64GERPP, do_ger, gen_helper_XVF64GERPP)
   3163 TRANS(XVF64GERPN, do_ger, gen_helper_XVF64GERPN)
   3164 TRANS(XVF64GERNP, do_ger, gen_helper_XVF64GERNP)
   3165 TRANS(XVF64GERNN, do_ger, gen_helper_XVF64GERNN)
   3166 
   3167 TRANS64(PMXVBF16GER2, do_ger, gen_helper_XVBF16GER2)
   3168 TRANS64(PMXVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
   3169 TRANS64(PMXVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
   3170 TRANS64(PMXVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
   3171 TRANS64(PMXVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
   3172 
   3173 TRANS64(PMXVF16GER2, do_ger, gen_helper_XVF16GER2)
   3174 TRANS64(PMXVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
   3175 TRANS64(PMXVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
   3176 TRANS64(PMXVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
   3177 TRANS64(PMXVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
   3178 
   3179 TRANS64(PMXVF32GER, do_ger, gen_helper_XVF32GER)
   3180 TRANS64(PMXVF32GERPP, do_ger, gen_helper_XVF32GERPP)
   3181 TRANS64(PMXVF32GERPN, do_ger, gen_helper_XVF32GERPN)
   3182 TRANS64(PMXVF32GERNP, do_ger, gen_helper_XVF32GERNP)
   3183 TRANS64(PMXVF32GERNN, do_ger, gen_helper_XVF32GERNN)
   3184 
   3185 TRANS64(PMXVF64GER, do_ger, gen_helper_XVF64GER)
   3186 TRANS64(PMXVF64GERPP, do_ger, gen_helper_XVF64GERPP)
   3187 TRANS64(PMXVF64GERPN, do_ger, gen_helper_XVF64GERPN)
   3188 TRANS64(PMXVF64GERNP, do_ger, gen_helper_XVF64GERNP)
   3189 TRANS64(PMXVF64GERNN, do_ger, gen_helper_XVF64GERNN)
   3190 
   3191 #undef GEN_XX2FORM
   3192 #undef GEN_XX3FORM
   3193 #undef GEN_XX2IFORM
   3194 #undef GEN_XX3_RC_FORM
   3195 #undef GEN_XX3FORM_DM
   3196 #undef VSX_LOGICAL