qemu/target-ppc/translate/vmx-impl.inc.c
<<
>>
Prefs
   1/*
   2 * translate/vmx-impl.c
   3 *
   4 * Altivec/VMX translation
   5 */
   6
   7/***                      Altivec vector extension                         ***/
   8/* Altivec registers moves */
   9
  10static inline TCGv_ptr gen_avr_ptr(int reg)
  11{
  12    TCGv_ptr r = tcg_temp_new_ptr();
  13    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, avr[reg]));
  14    return r;
  15}
  16
  17#define GEN_VR_LDX(name, opc2, opc3)                                          \
  18static void glue(gen_, name)(DisasContext *ctx)                                       \
  19{                                                                             \
  20    TCGv EA;                                                                  \
  21    if (unlikely(!ctx->altivec_enabled)) {                                    \
  22        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
  23        return;                                                               \
  24    }                                                                         \
  25    gen_set_access_type(ctx, ACCESS_INT);                                     \
  26    EA = tcg_temp_new();                                                      \
  27    gen_addr_reg_index(ctx, EA);                                              \
  28    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
  29    /* We only need to swap high and low halves. gen_qemu_ld64_i64 does       \
  30       necessary 64-bit byteswap already. */                                  \
  31    if (ctx->le_mode) {                                                       \
  32        gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                \
  33        tcg_gen_addi_tl(EA, EA, 8);                                           \
  34        gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                \
  35    } else {                                                                  \
  36        gen_qemu_ld64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                \
  37        tcg_gen_addi_tl(EA, EA, 8);                                           \
  38        gen_qemu_ld64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                \
  39    }                                                                         \
  40    tcg_temp_free(EA);                                                        \
  41}
  42
  43#define GEN_VR_STX(name, opc2, opc3)                                          \
  44static void gen_st##name(DisasContext *ctx)                                   \
  45{                                                                             \
  46    TCGv EA;                                                                  \
  47    if (unlikely(!ctx->altivec_enabled)) {                                    \
  48        gen_exception(ctx, POWERPC_EXCP_VPU);                                 \
  49        return;                                                               \
  50    }                                                                         \
  51    gen_set_access_type(ctx, ACCESS_INT);                                     \
  52    EA = tcg_temp_new();                                                      \
  53    gen_addr_reg_index(ctx, EA);                                              \
  54    tcg_gen_andi_tl(EA, EA, ~0xf);                                            \
  55    /* We only need to swap high and low halves. gen_qemu_st64_i64 does       \
  56       necessary 64-bit byteswap already. */                                  \
  57    if (ctx->le_mode) {                                                       \
  58        gen_qemu_st64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                \
  59        tcg_gen_addi_tl(EA, EA, 8);                                           \
  60        gen_qemu_st64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                \
  61    } else {                                                                  \
  62        gen_qemu_st64_i64(ctx, cpu_avrh[rD(ctx->opcode)], EA);                \
  63        tcg_gen_addi_tl(EA, EA, 8);                                           \
  64        gen_qemu_st64_i64(ctx, cpu_avrl[rD(ctx->opcode)], EA);                \
  65    }                                                                         \
  66    tcg_temp_free(EA);                                                        \
  67}
  68
  69#define GEN_VR_LVE(name, opc2, opc3, size)                              \
  70static void gen_lve##name(DisasContext *ctx)                            \
  71    {                                                                   \
  72        TCGv EA;                                                        \
  73        TCGv_ptr rs;                                                    \
  74        if (unlikely(!ctx->altivec_enabled)) {                          \
  75            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
  76            return;                                                     \
  77        }                                                               \
  78        gen_set_access_type(ctx, ACCESS_INT);                           \
  79        EA = tcg_temp_new();                                            \
  80        gen_addr_reg_index(ctx, EA);                                    \
  81        if (size > 1) {                                                 \
  82            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
  83        }                                                               \
  84        rs = gen_avr_ptr(rS(ctx->opcode));                              \
  85        gen_helper_lve##name(cpu_env, rs, EA);                          \
  86        tcg_temp_free(EA);                                              \
  87        tcg_temp_free_ptr(rs);                                          \
  88    }
  89
  90#define GEN_VR_STVE(name, opc2, opc3, size)                             \
  91static void gen_stve##name(DisasContext *ctx)                           \
  92    {                                                                   \
  93        TCGv EA;                                                        \
  94        TCGv_ptr rs;                                                    \
  95        if (unlikely(!ctx->altivec_enabled)) {                          \
  96            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
  97            return;                                                     \
  98        }                                                               \
  99        gen_set_access_type(ctx, ACCESS_INT);                           \
 100        EA = tcg_temp_new();                                            \
 101        gen_addr_reg_index(ctx, EA);                                    \
 102        if (size > 1) {                                                 \
 103            tcg_gen_andi_tl(EA, EA, ~(size - 1));                       \
 104        }                                                               \
 105        rs = gen_avr_ptr(rS(ctx->opcode));                              \
 106        gen_helper_stve##name(cpu_env, rs, EA);                         \
 107        tcg_temp_free(EA);                                              \
 108        tcg_temp_free_ptr(rs);                                          \
 109    }
 110
 111GEN_VR_LDX(lvx, 0x07, 0x03);
 112/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
 113GEN_VR_LDX(lvxl, 0x07, 0x0B);
 114
 115GEN_VR_LVE(bx, 0x07, 0x00, 1);
 116GEN_VR_LVE(hx, 0x07, 0x01, 2);
 117GEN_VR_LVE(wx, 0x07, 0x02, 4);
 118
 119GEN_VR_STX(svx, 0x07, 0x07);
 120/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
 121GEN_VR_STX(svxl, 0x07, 0x0F);
 122
 123GEN_VR_STVE(bx, 0x07, 0x04, 1);
 124GEN_VR_STVE(hx, 0x07, 0x05, 2);
 125GEN_VR_STVE(wx, 0x07, 0x06, 4);
 126
 127static void gen_lvsl(DisasContext *ctx)
 128{
 129    TCGv_ptr rd;
 130    TCGv EA;
 131    if (unlikely(!ctx->altivec_enabled)) {
 132        gen_exception(ctx, POWERPC_EXCP_VPU);
 133        return;
 134    }
 135    EA = tcg_temp_new();
 136    gen_addr_reg_index(ctx, EA);
 137    rd = gen_avr_ptr(rD(ctx->opcode));
 138    gen_helper_lvsl(rd, EA);
 139    tcg_temp_free(EA);
 140    tcg_temp_free_ptr(rd);
 141}
 142
 143static void gen_lvsr(DisasContext *ctx)
 144{
 145    TCGv_ptr rd;
 146    TCGv EA;
 147    if (unlikely(!ctx->altivec_enabled)) {
 148        gen_exception(ctx, POWERPC_EXCP_VPU);
 149        return;
 150    }
 151    EA = tcg_temp_new();
 152    gen_addr_reg_index(ctx, EA);
 153    rd = gen_avr_ptr(rD(ctx->opcode));
 154    gen_helper_lvsr(rd, EA);
 155    tcg_temp_free(EA);
 156    tcg_temp_free_ptr(rd);
 157}
 158
 159static void gen_mfvscr(DisasContext *ctx)
 160{
 161    TCGv_i32 t;
 162    if (unlikely(!ctx->altivec_enabled)) {
 163        gen_exception(ctx, POWERPC_EXCP_VPU);
 164        return;
 165    }
 166    tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
 167    t = tcg_temp_new_i32();
 168    tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, vscr));
 169    tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
 170    tcg_temp_free_i32(t);
 171}
 172
 173static void gen_mtvscr(DisasContext *ctx)
 174{
 175    TCGv_ptr p;
 176    if (unlikely(!ctx->altivec_enabled)) {
 177        gen_exception(ctx, POWERPC_EXCP_VPU);
 178        return;
 179    }
 180    p = gen_avr_ptr(rB(ctx->opcode));
 181    gen_helper_mtvscr(cpu_env, p);
 182    tcg_temp_free_ptr(p);
 183}
 184
 185#define GEN_VX_VMUL10(name, add_cin, ret_carry)                         \
 186static void glue(gen_, name)(DisasContext *ctx)                         \
 187{                                                                       \
 188    TCGv_i64 t0 = tcg_temp_new_i64();                                   \
 189    TCGv_i64 t1 = tcg_temp_new_i64();                                   \
 190    TCGv_i64 t2 = tcg_temp_new_i64();                                   \
 191    TCGv_i64 ten, z;                                                    \
 192                                                                        \
 193    if (unlikely(!ctx->altivec_enabled)) {                              \
 194        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 195        return;                                                         \
 196    }                                                                   \
 197                                                                        \
 198    ten = tcg_const_i64(10);                                            \
 199    z = tcg_const_i64(0);                                               \
 200                                                                        \
 201    if (add_cin) {                                                      \
 202        tcg_gen_mulu2_i64(t0, t1, cpu_avrl[rA(ctx->opcode)], ten);      \
 203        tcg_gen_andi_i64(t2, cpu_avrl[rB(ctx->opcode)], 0xF);           \
 204        tcg_gen_add2_i64(cpu_avrl[rD(ctx->opcode)], t2, t0, t1, t2, z); \
 205    } else {                                                            \
 206        tcg_gen_mulu2_i64(cpu_avrl[rD(ctx->opcode)], t2,                \
 207                          cpu_avrl[rA(ctx->opcode)], ten);              \
 208    }                                                                   \
 209                                                                        \
 210    if (ret_carry) {                                                    \
 211        tcg_gen_mulu2_i64(t0, t1, cpu_avrh[rA(ctx->opcode)], ten);      \
 212        tcg_gen_add2_i64(t0, cpu_avrl[rD(ctx->opcode)], t0, t1, t2, z); \
 213        tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);                 \
 214    } else {                                                            \
 215        tcg_gen_mul_i64(t0, cpu_avrh[rA(ctx->opcode)], ten);            \
 216        tcg_gen_add_i64(cpu_avrh[rD(ctx->opcode)], t0, t2);             \
 217    }                                                                   \
 218                                                                        \
 219    tcg_temp_free_i64(t0);                                              \
 220    tcg_temp_free_i64(t1);                                              \
 221    tcg_temp_free_i64(t2);                                              \
 222    tcg_temp_free_i64(ten);                                             \
 223    tcg_temp_free_i64(z);                                               \
 224}                                                                       \
 225
 226GEN_VX_VMUL10(vmul10uq, 0, 0);
 227GEN_VX_VMUL10(vmul10euq, 1, 0);
 228GEN_VX_VMUL10(vmul10cuq, 0, 1);
 229GEN_VX_VMUL10(vmul10ecuq, 1, 1);
 230
 231/* Logical operations */
 232#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3)                        \
 233static void glue(gen_, name)(DisasContext *ctx)                                 \
 234{                                                                       \
 235    if (unlikely(!ctx->altivec_enabled)) {                              \
 236        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 237        return;                                                         \
 238    }                                                                   \
 239    tcg_op(cpu_avrh[rD(ctx->opcode)], cpu_avrh[rA(ctx->opcode)], cpu_avrh[rB(ctx->opcode)]); \
 240    tcg_op(cpu_avrl[rD(ctx->opcode)], cpu_avrl[rA(ctx->opcode)], cpu_avrl[rB(ctx->opcode)]); \
 241}
 242
 243GEN_VX_LOGICAL(vand, tcg_gen_and_i64, 2, 16);
 244GEN_VX_LOGICAL(vandc, tcg_gen_andc_i64, 2, 17);
 245GEN_VX_LOGICAL(vor, tcg_gen_or_i64, 2, 18);
 246GEN_VX_LOGICAL(vxor, tcg_gen_xor_i64, 2, 19);
 247GEN_VX_LOGICAL(vnor, tcg_gen_nor_i64, 2, 20);
 248GEN_VX_LOGICAL(veqv, tcg_gen_eqv_i64, 2, 26);
 249GEN_VX_LOGICAL(vnand, tcg_gen_nand_i64, 2, 22);
 250GEN_VX_LOGICAL(vorc, tcg_gen_orc_i64, 2, 21);
 251
 252#define GEN_VXFORM(name, opc2, opc3)                                    \
 253static void glue(gen_, name)(DisasContext *ctx)                                 \
 254{                                                                       \
 255    TCGv_ptr ra, rb, rd;                                                \
 256    if (unlikely(!ctx->altivec_enabled)) {                              \
 257        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 258        return;                                                         \
 259    }                                                                   \
 260    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
 261    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
 262    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
 263    gen_helper_##name (rd, ra, rb);                                     \
 264    tcg_temp_free_ptr(ra);                                              \
 265    tcg_temp_free_ptr(rb);                                              \
 266    tcg_temp_free_ptr(rd);                                              \
 267}
 268
 269#define GEN_VXFORM_ENV(name, opc2, opc3)                                \
 270static void glue(gen_, name)(DisasContext *ctx)                         \
 271{                                                                       \
 272    TCGv_ptr ra, rb, rd;                                                \
 273    if (unlikely(!ctx->altivec_enabled)) {                              \
 274        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 275        return;                                                         \
 276    }                                                                   \
 277    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
 278    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
 279    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
 280    gen_helper_##name(cpu_env, rd, ra, rb);                             \
 281    tcg_temp_free_ptr(ra);                                              \
 282    tcg_temp_free_ptr(rb);                                              \
 283    tcg_temp_free_ptr(rd);                                              \
 284}
 285
 286#define GEN_VXFORM3(name, opc2, opc3)                                   \
 287static void glue(gen_, name)(DisasContext *ctx)                         \
 288{                                                                       \
 289    TCGv_ptr ra, rb, rc, rd;                                            \
 290    if (unlikely(!ctx->altivec_enabled)) {                              \
 291        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 292        return;                                                         \
 293    }                                                                   \
 294    ra = gen_avr_ptr(rA(ctx->opcode));                                  \
 295    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
 296    rc = gen_avr_ptr(rC(ctx->opcode));                                  \
 297    rd = gen_avr_ptr(rD(ctx->opcode));                                  \
 298    gen_helper_##name(rd, ra, rb, rc);                                  \
 299    tcg_temp_free_ptr(ra);                                              \
 300    tcg_temp_free_ptr(rb);                                              \
 301    tcg_temp_free_ptr(rc);                                              \
 302    tcg_temp_free_ptr(rd);                                              \
 303}
 304
 305/*
 306 * Support for Altivec instruction pairs that use bit 31 (Rc) as
 307 * an opcode bit.  In general, these pairs come from different
 308 * versions of the ISA, so we must also support a pair of flags for
 309 * each instruction.
 310 */
 311#define GEN_VXFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)          \
 312static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
 313{                                                                      \
 314    if ((Rc(ctx->opcode) == 0) &&                                      \
 315        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
 316        gen_##name0(ctx);                                              \
 317    } else if ((Rc(ctx->opcode) == 1) &&                               \
 318        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
 319        gen_##name1(ctx);                                              \
 320    } else {                                                           \
 321        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
 322    }                                                                  \
 323}
 324
 325/* Adds support to provide invalid mask */
 326#define GEN_VXFORM_DUAL_EXT(name0, flg0, flg2_0, inval0,                \
 327                            name1, flg1, flg2_1, inval1)                \
 328static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
 329{                                                                       \
 330    if ((Rc(ctx->opcode) == 0) &&                                       \
 331        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0)) &&  \
 332        !(ctx->opcode & inval0)) {                                      \
 333        gen_##name0(ctx);                                               \
 334    } else if ((Rc(ctx->opcode) == 1) &&                                \
 335               ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1)) && \
 336               !(ctx->opcode & inval1)) {                               \
 337        gen_##name1(ctx);                                               \
 338    } else {                                                            \
 339        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);             \
 340    }                                                                   \
 341}
 342
 343GEN_VXFORM(vaddubm, 0, 0);
 344GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0,       \
 345                    vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
 346GEN_VXFORM(vadduhm, 0, 1);
 347GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE,  \
 348                vmul10ecuq, PPC_NONE, PPC2_ISA300)
 349GEN_VXFORM(vadduwm, 0, 2);
 350GEN_VXFORM(vaddudm, 0, 3);
 351GEN_VXFORM(vsububm, 0, 16);
 352GEN_VXFORM(vsubuhm, 0, 17);
 353GEN_VXFORM(vsubuwm, 0, 18);
 354GEN_VXFORM(vsubudm, 0, 19);
 355GEN_VXFORM(vmaxub, 1, 0);
 356GEN_VXFORM(vmaxuh, 1, 1);
 357GEN_VXFORM(vmaxuw, 1, 2);
 358GEN_VXFORM(vmaxud, 1, 3);
 359GEN_VXFORM(vmaxsb, 1, 4);
 360GEN_VXFORM(vmaxsh, 1, 5);
 361GEN_VXFORM(vmaxsw, 1, 6);
 362GEN_VXFORM(vmaxsd, 1, 7);
 363GEN_VXFORM(vminub, 1, 8);
 364GEN_VXFORM(vminuh, 1, 9);
 365GEN_VXFORM(vminuw, 1, 10);
 366GEN_VXFORM(vminud, 1, 11);
 367GEN_VXFORM(vminsb, 1, 12);
 368GEN_VXFORM(vminsh, 1, 13);
 369GEN_VXFORM(vminsw, 1, 14);
 370GEN_VXFORM(vminsd, 1, 15);
 371GEN_VXFORM(vavgub, 1, 16);
 372GEN_VXFORM(vabsdub, 1, 16);
 373GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
 374                vabsdub, PPC_NONE, PPC2_ISA300)
 375GEN_VXFORM(vavguh, 1, 17);
 376GEN_VXFORM(vabsduh, 1, 17);
 377GEN_VXFORM_DUAL(vavguh, PPC_ALTIVEC, PPC_NONE, \
 378                vabsduh, PPC_NONE, PPC2_ISA300)
 379GEN_VXFORM(vavguw, 1, 18);
 380GEN_VXFORM(vabsduw, 1, 18);
 381GEN_VXFORM_DUAL(vavguw, PPC_ALTIVEC, PPC_NONE, \
 382                vabsduw, PPC_NONE, PPC2_ISA300)
 383GEN_VXFORM(vavgsb, 1, 20);
 384GEN_VXFORM(vavgsh, 1, 21);
 385GEN_VXFORM(vavgsw, 1, 22);
 386GEN_VXFORM(vmrghb, 6, 0);
 387GEN_VXFORM(vmrghh, 6, 1);
 388GEN_VXFORM(vmrghw, 6, 2);
 389GEN_VXFORM(vmrglb, 6, 4);
 390GEN_VXFORM(vmrglh, 6, 5);
 391GEN_VXFORM(vmrglw, 6, 6);
 392
 393static void gen_vmrgew(DisasContext *ctx)
 394{
 395    TCGv_i64 tmp;
 396    int VT, VA, VB;
 397    if (unlikely(!ctx->altivec_enabled)) {
 398        gen_exception(ctx, POWERPC_EXCP_VPU);
 399        return;
 400    }
 401    VT = rD(ctx->opcode);
 402    VA = rA(ctx->opcode);
 403    VB = rB(ctx->opcode);
 404    tmp = tcg_temp_new_i64();
 405    tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32);
 406    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32);
 407    tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32);
 408    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32);
 409    tcg_temp_free_i64(tmp);
 410}
 411
 412static void gen_vmrgow(DisasContext *ctx)
 413{
 414    int VT, VA, VB;
 415    if (unlikely(!ctx->altivec_enabled)) {
 416        gen_exception(ctx, POWERPC_EXCP_VPU);
 417        return;
 418    }
 419    VT = rD(ctx->opcode);
 420    VA = rA(ctx->opcode);
 421    VB = rB(ctx->opcode);
 422
 423    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32);
 424    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32);
 425}
 426
 427GEN_VXFORM(vmuloub, 4, 0);
 428GEN_VXFORM(vmulouh, 4, 1);
 429GEN_VXFORM(vmulouw, 4, 2);
 430GEN_VXFORM(vmuluwm, 4, 2);
 431GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
 432                vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
 433GEN_VXFORM(vmulosb, 4, 4);
 434GEN_VXFORM(vmulosh, 4, 5);
 435GEN_VXFORM(vmulosw, 4, 6);
 436GEN_VXFORM(vmuleub, 4, 8);
 437GEN_VXFORM(vmuleuh, 4, 9);
 438GEN_VXFORM(vmuleuw, 4, 10);
 439GEN_VXFORM(vmulesb, 4, 12);
 440GEN_VXFORM(vmulesh, 4, 13);
 441GEN_VXFORM(vmulesw, 4, 14);
 442GEN_VXFORM(vslb, 2, 4);
 443GEN_VXFORM(vslh, 2, 5);
 444GEN_VXFORM(vslw, 2, 6);
 445GEN_VXFORM(vrlwnm, 2, 6);
 446GEN_VXFORM_DUAL(vslw, PPC_ALTIVEC, PPC_NONE, \
 447                vrlwnm, PPC_NONE, PPC2_ISA300)
 448GEN_VXFORM(vsld, 2, 23);
 449GEN_VXFORM(vsrb, 2, 8);
 450GEN_VXFORM(vsrh, 2, 9);
 451GEN_VXFORM(vsrw, 2, 10);
 452GEN_VXFORM(vsrd, 2, 27);
 453GEN_VXFORM(vsrab, 2, 12);
 454GEN_VXFORM(vsrah, 2, 13);
 455GEN_VXFORM(vsraw, 2, 14);
 456GEN_VXFORM(vsrad, 2, 15);
 457GEN_VXFORM(vsrv, 2, 28);
 458GEN_VXFORM(vslv, 2, 29);
 459GEN_VXFORM(vslo, 6, 16);
 460GEN_VXFORM(vsro, 6, 17);
 461GEN_VXFORM(vaddcuw, 0, 6);
 462GEN_VXFORM(vsubcuw, 0, 22);
 463GEN_VXFORM_ENV(vaddubs, 0, 8);
 464GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0,       \
 465                    vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
 466GEN_VXFORM_ENV(vadduhs, 0, 9);
 467GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
 468                vmul10euq, PPC_NONE, PPC2_ISA300)
 469GEN_VXFORM_ENV(vadduws, 0, 10);
 470GEN_VXFORM_ENV(vaddsbs, 0, 12);
 471GEN_VXFORM_ENV(vaddshs, 0, 13);
 472GEN_VXFORM_ENV(vaddsws, 0, 14);
 473GEN_VXFORM_ENV(vsububs, 0, 24);
 474GEN_VXFORM_ENV(vsubuhs, 0, 25);
 475GEN_VXFORM_ENV(vsubuws, 0, 26);
 476GEN_VXFORM_ENV(vsubsbs, 0, 28);
 477GEN_VXFORM_ENV(vsubshs, 0, 29);
 478GEN_VXFORM_ENV(vsubsws, 0, 30);
 479GEN_VXFORM(vadduqm, 0, 4);
 480GEN_VXFORM(vaddcuq, 0, 5);
 481GEN_VXFORM3(vaddeuqm, 30, 0);
 482GEN_VXFORM3(vaddecuq, 30, 0);
 483GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
 484            vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
 485GEN_VXFORM(vsubuqm, 0, 20);
 486GEN_VXFORM(vsubcuq, 0, 21);
 487GEN_VXFORM3(vsubeuqm, 31, 0);
 488GEN_VXFORM3(vsubecuq, 31, 0);
 489GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
 490            vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
 491GEN_VXFORM(vrlb, 2, 0);
 492GEN_VXFORM(vrlh, 2, 1);
 493GEN_VXFORM(vrlw, 2, 2);
 494GEN_VXFORM(vrlwmi, 2, 2);
 495GEN_VXFORM_DUAL(vrlw, PPC_ALTIVEC, PPC_NONE, \
 496                vrlwmi, PPC_NONE, PPC2_ISA300)
 497GEN_VXFORM(vrld, 2, 3);
 498GEN_VXFORM(vrldmi, 2, 3);
 499GEN_VXFORM_DUAL(vrld, PPC_NONE, PPC2_ALTIVEC_207, \
 500                vrldmi, PPC_NONE, PPC2_ISA300)
 501GEN_VXFORM(vsl, 2, 7);
 502GEN_VXFORM(vrldnm, 2, 7);
 503GEN_VXFORM_DUAL(vsl, PPC_ALTIVEC, PPC_NONE, \
 504                vrldnm, PPC_NONE, PPC2_ISA300)
 505GEN_VXFORM(vsr, 2, 11);
 506GEN_VXFORM_ENV(vpkuhum, 7, 0);
 507GEN_VXFORM_ENV(vpkuwum, 7, 1);
 508GEN_VXFORM_ENV(vpkudum, 7, 17);
 509GEN_VXFORM_ENV(vpkuhus, 7, 2);
 510GEN_VXFORM_ENV(vpkuwus, 7, 3);
 511GEN_VXFORM_ENV(vpkudus, 7, 19);
 512GEN_VXFORM_ENV(vpkshus, 7, 4);
 513GEN_VXFORM_ENV(vpkswus, 7, 5);
 514GEN_VXFORM_ENV(vpksdus, 7, 21);
 515GEN_VXFORM_ENV(vpkshss, 7, 6);
 516GEN_VXFORM_ENV(vpkswss, 7, 7);
 517GEN_VXFORM_ENV(vpksdss, 7, 23);
 518GEN_VXFORM(vpkpx, 7, 12);
 519GEN_VXFORM_ENV(vsum4ubs, 4, 24);
 520GEN_VXFORM_ENV(vsum4sbs, 4, 28);
 521GEN_VXFORM_ENV(vsum4shs, 4, 25);
 522GEN_VXFORM_ENV(vsum2sws, 4, 26);
 523GEN_VXFORM_ENV(vsumsws, 4, 30);
 524GEN_VXFORM_ENV(vaddfp, 5, 0);
 525GEN_VXFORM_ENV(vsubfp, 5, 1);
 526GEN_VXFORM_ENV(vmaxfp, 5, 16);
 527GEN_VXFORM_ENV(vminfp, 5, 17);
 528
 529#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
 530static void glue(gen_, name)(DisasContext *ctx)                         \
 531    {                                                                   \
 532        TCGv_ptr ra, rb, rd;                                            \
 533        if (unlikely(!ctx->altivec_enabled)) {                          \
 534            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 535            return;                                                     \
 536        }                                                               \
 537        ra = gen_avr_ptr(rA(ctx->opcode));                              \
 538        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 539        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 540        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
 541        tcg_temp_free_ptr(ra);                                          \
 542        tcg_temp_free_ptr(rb);                                          \
 543        tcg_temp_free_ptr(rd);                                          \
 544    }
 545
 546#define GEN_VXRFORM(name, opc2, opc3)                                \
 547    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
 548    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
 549
 550/*
 551 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
 552 * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
 553 * come from different versions of the ISA, so we must also support a
 554 * pair of flags for each instruction.
 555 */
 556#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
 557static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
 558{                                                                      \
 559    if ((Rc(ctx->opcode) == 0) &&                                      \
 560        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
 561        if (Rc21(ctx->opcode) == 0) {                                  \
 562            gen_##name0(ctx);                                          \
 563        } else {                                                       \
 564            gen_##name0##_(ctx);                                       \
 565        }                                                              \
 566    } else if ((Rc(ctx->opcode) == 1) &&                               \
 567        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
 568        if (Rc21(ctx->opcode) == 0) {                                  \
 569            gen_##name1(ctx);                                          \
 570        } else {                                                       \
 571            gen_##name1##_(ctx);                                       \
 572        }                                                              \
 573    } else {                                                           \
 574        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
 575    }                                                                  \
 576}
 577
 578GEN_VXRFORM(vcmpequb, 3, 0)
 579GEN_VXRFORM(vcmpequh, 3, 1)
 580GEN_VXRFORM(vcmpequw, 3, 2)
 581GEN_VXRFORM(vcmpequd, 3, 3)
 582GEN_VXRFORM(vcmpnezb, 3, 4)
 583GEN_VXRFORM(vcmpnezh, 3, 5)
 584GEN_VXRFORM(vcmpnezw, 3, 6)
 585GEN_VXRFORM(vcmpgtsb, 3, 12)
 586GEN_VXRFORM(vcmpgtsh, 3, 13)
 587GEN_VXRFORM(vcmpgtsw, 3, 14)
 588GEN_VXRFORM(vcmpgtsd, 3, 15)
 589GEN_VXRFORM(vcmpgtub, 3, 8)
 590GEN_VXRFORM(vcmpgtuh, 3, 9)
 591GEN_VXRFORM(vcmpgtuw, 3, 10)
 592GEN_VXRFORM(vcmpgtud, 3, 11)
 593GEN_VXRFORM(vcmpeqfp, 3, 3)
 594GEN_VXRFORM(vcmpgefp, 3, 7)
 595GEN_VXRFORM(vcmpgtfp, 3, 11)
 596GEN_VXRFORM(vcmpbfp, 3, 15)
 597GEN_VXRFORM(vcmpneb, 3, 0)
 598GEN_VXRFORM(vcmpneh, 3, 1)
 599GEN_VXRFORM(vcmpnew, 3, 2)
 600
 601GEN_VXRFORM_DUAL(vcmpequb, PPC_ALTIVEC, PPC_NONE, \
 602                 vcmpneb, PPC_NONE, PPC2_ISA300)
 603GEN_VXRFORM_DUAL(vcmpequh, PPC_ALTIVEC, PPC_NONE, \
 604                 vcmpneh, PPC_NONE, PPC2_ISA300)
 605GEN_VXRFORM_DUAL(vcmpequw, PPC_ALTIVEC, PPC_NONE, \
 606                 vcmpnew, PPC_NONE, PPC2_ISA300)
 607GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
 608                 vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
 609GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
 610                 vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
 611GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
 612                 vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
 613
 614#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
 615static void glue(gen_, name)(DisasContext *ctx)                         \
 616    {                                                                   \
 617        TCGv_ptr rd;                                                    \
 618        TCGv_i32 simm;                                                  \
 619        if (unlikely(!ctx->altivec_enabled)) {                          \
 620            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 621            return;                                                     \
 622        }                                                               \
 623        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
 624        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 625        gen_helper_##name (rd, simm);                                   \
 626        tcg_temp_free_i32(simm);                                        \
 627        tcg_temp_free_ptr(rd);                                          \
 628    }
 629
 630GEN_VXFORM_SIMM(vspltisb, 6, 12);
 631GEN_VXFORM_SIMM(vspltish, 6, 13);
 632GEN_VXFORM_SIMM(vspltisw, 6, 14);
 633
 634#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
 635static void glue(gen_, name)(DisasContext *ctx)                                 \
 636    {                                                                   \
 637        TCGv_ptr rb, rd;                                                \
 638        if (unlikely(!ctx->altivec_enabled)) {                          \
 639            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 640            return;                                                     \
 641        }                                                               \
 642        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 643        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 644        gen_helper_##name (rd, rb);                                     \
 645        tcg_temp_free_ptr(rb);                                          \
 646        tcg_temp_free_ptr(rd);                                         \
 647    }
 648
 649#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
 650static void glue(gen_, name)(DisasContext *ctx)                         \
 651    {                                                                   \
 652        TCGv_ptr rb, rd;                                                \
 653                                                                        \
 654        if (unlikely(!ctx->altivec_enabled)) {                          \
 655            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 656            return;                                                     \
 657        }                                                               \
 658        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 659        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 660        gen_helper_##name(cpu_env, rd, rb);                             \
 661        tcg_temp_free_ptr(rb);                                          \
 662        tcg_temp_free_ptr(rd);                                          \
 663    }
 664
 665#define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4)                        \
 666static void glue(gen_, name)(DisasContext *ctx)                         \
 667    {                                                                   \
 668        TCGv_ptr rb, rd;                                                \
 669        if (unlikely(!ctx->altivec_enabled)) {                          \
 670            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 671            return;                                                     \
 672        }                                                               \
 673        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 674        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 675        gen_helper_##name(rd, rb);                                      \
 676        tcg_temp_free_ptr(rb);                                          \
 677        tcg_temp_free_ptr(rd);                                          \
 678    }
 679
 680#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4)                        \
 681static void glue(gen_, name)(DisasContext *ctx)                         \
 682    {                                                                   \
 683        TCGv_ptr rb;                                                    \
 684        if (unlikely(!ctx->altivec_enabled)) {                          \
 685            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 686            return;                                                     \
 687        }                                                               \
 688        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 689        gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb);                \
 690        tcg_temp_free_ptr(rb);                                          \
 691    }
 692GEN_VXFORM_NOA(vupkhsb, 7, 8);
 693GEN_VXFORM_NOA(vupkhsh, 7, 9);
 694GEN_VXFORM_NOA(vupkhsw, 7, 25);
 695GEN_VXFORM_NOA(vupklsb, 7, 10);
 696GEN_VXFORM_NOA(vupklsh, 7, 11);
 697GEN_VXFORM_NOA(vupklsw, 7, 27);
 698GEN_VXFORM_NOA(vupkhpx, 7, 13);
 699GEN_VXFORM_NOA(vupklpx, 7, 15);
 700GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
 701GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
 702GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
 703GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
 704GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
 705GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
 706GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
 707GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
 708GEN_VXFORM_NOA(vprtybw, 1, 24);
 709GEN_VXFORM_NOA(vprtybd, 1, 24);
 710GEN_VXFORM_NOA(vprtybq, 1, 24);
 711
 712#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
 713static void glue(gen_, name)(DisasContext *ctx)                                 \
 714    {                                                                   \
 715        TCGv_ptr rd;                                                    \
 716        TCGv_i32 simm;                                                  \
 717        if (unlikely(!ctx->altivec_enabled)) {                          \
 718            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 719            return;                                                     \
 720        }                                                               \
 721        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
 722        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 723        gen_helper_##name (rd, simm);                                   \
 724        tcg_temp_free_i32(simm);                                        \
 725        tcg_temp_free_ptr(rd);                                          \
 726    }
 727
 728#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
 729static void glue(gen_, name)(DisasContext *ctx)                                 \
 730    {                                                                   \
 731        TCGv_ptr rb, rd;                                                \
 732        TCGv_i32 uimm;                                                  \
 733        if (unlikely(!ctx->altivec_enabled)) {                          \
 734            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 735            return;                                                     \
 736        }                                                               \
 737        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
 738        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 739        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 740        gen_helper_##name (rd, rb, uimm);                               \
 741        tcg_temp_free_i32(uimm);                                        \
 742        tcg_temp_free_ptr(rb);                                          \
 743        tcg_temp_free_ptr(rd);                                          \
 744    }
 745
 746#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
 747static void glue(gen_, name)(DisasContext *ctx)                         \
 748    {                                                                   \
 749        TCGv_ptr rb, rd;                                                \
 750        TCGv_i32 uimm;                                                  \
 751                                                                        \
 752        if (unlikely(!ctx->altivec_enabled)) {                          \
 753            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 754            return;                                                     \
 755        }                                                               \
 756        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
 757        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 758        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 759        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
 760        tcg_temp_free_i32(uimm);                                        \
 761        tcg_temp_free_ptr(rb);                                          \
 762        tcg_temp_free_ptr(rd);                                          \
 763    }
 764
 765#define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max)              \
 766static void glue(gen_, name)(DisasContext *ctx)                         \
 767    {                                                                   \
 768        TCGv_ptr rb, rd;                                                \
 769        uint8_t uimm = UIMM4(ctx->opcode);                              \
 770        TCGv_i32 t0 = tcg_temp_new_i32();                               \
 771        if (unlikely(!ctx->altivec_enabled)) {                          \
 772            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 773            return;                                                     \
 774        }                                                               \
 775        if (uimm > splat_max) {                                         \
 776            uimm = 0;                                                   \
 777        }                                                               \
 778        tcg_gen_movi_i32(t0, uimm);                                     \
 779        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 780        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 781        gen_helper_##name(rd, rb, t0);                                  \
 782        tcg_temp_free_i32(t0);                                          \
 783        tcg_temp_free_ptr(rb);                                          \
 784        tcg_temp_free_ptr(rd);                                          \
 785    }
 786
 787GEN_VXFORM_UIMM(vspltb, 6, 8);
 788GEN_VXFORM_UIMM(vsplth, 6, 9);
 789GEN_VXFORM_UIMM(vspltw, 6, 10);
 790GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
 791GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
 792GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
 793GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
 794GEN_VXFORM_UIMM_SPLAT(vinsertb, 6, 12, 15);
 795GEN_VXFORM_UIMM_SPLAT(vinserth, 6, 13, 14);
 796GEN_VXFORM_UIMM_SPLAT(vinsertw, 6, 14, 12);
 797GEN_VXFORM_UIMM_SPLAT(vinsertd, 6, 15, 8);
 798GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
 799GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
 800GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
 801GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
 802GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
 803                vextractub, PPC_NONE, PPC2_ISA300);
 804GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
 805                vextractuh, PPC_NONE, PPC2_ISA300);
 806GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
 807                vextractuw, PPC_NONE, PPC2_ISA300);
 808GEN_VXFORM_DUAL(vspltisb, PPC_ALTIVEC, PPC_NONE,
 809                vinsertb, PPC_NONE, PPC2_ISA300);
 810GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
 811                vinserth, PPC_NONE, PPC2_ISA300);
 812GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
 813                vinsertw, PPC_NONE, PPC2_ISA300);
 814
 815static void gen_vsldoi(DisasContext *ctx)
 816{
 817    TCGv_ptr ra, rb, rd;
 818    TCGv_i32 sh;
 819    if (unlikely(!ctx->altivec_enabled)) {
 820        gen_exception(ctx, POWERPC_EXCP_VPU);
 821        return;
 822    }
 823    ra = gen_avr_ptr(rA(ctx->opcode));
 824    rb = gen_avr_ptr(rB(ctx->opcode));
 825    rd = gen_avr_ptr(rD(ctx->opcode));
 826    sh = tcg_const_i32(VSH(ctx->opcode));
 827    gen_helper_vsldoi (rd, ra, rb, sh);
 828    tcg_temp_free_ptr(ra);
 829    tcg_temp_free_ptr(rb);
 830    tcg_temp_free_ptr(rd);
 831    tcg_temp_free_i32(sh);
 832}
 833
 834#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
 835static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
 836    {                                                                   \
 837        TCGv_ptr ra, rb, rc, rd;                                        \
 838        if (unlikely(!ctx->altivec_enabled)) {                          \
 839            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 840            return;                                                     \
 841        }                                                               \
 842        ra = gen_avr_ptr(rA(ctx->opcode));                              \
 843        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 844        rc = gen_avr_ptr(rC(ctx->opcode));                              \
 845        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 846        if (Rc(ctx->opcode)) {                                          \
 847            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
 848        } else {                                                        \
 849            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
 850        }                                                               \
 851        tcg_temp_free_ptr(ra);                                          \
 852        tcg_temp_free_ptr(rb);                                          \
 853        tcg_temp_free_ptr(rc);                                          \
 854        tcg_temp_free_ptr(rd);                                          \
 855    }
 856
 857GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
 858
 859static void gen_vmladduhm(DisasContext *ctx)
 860{
 861    TCGv_ptr ra, rb, rc, rd;
 862    if (unlikely(!ctx->altivec_enabled)) {
 863        gen_exception(ctx, POWERPC_EXCP_VPU);
 864        return;
 865    }
 866    ra = gen_avr_ptr(rA(ctx->opcode));
 867    rb = gen_avr_ptr(rB(ctx->opcode));
 868    rc = gen_avr_ptr(rC(ctx->opcode));
 869    rd = gen_avr_ptr(rD(ctx->opcode));
 870    gen_helper_vmladduhm(rd, ra, rb, rc);
 871    tcg_temp_free_ptr(ra);
 872    tcg_temp_free_ptr(rb);
 873    tcg_temp_free_ptr(rc);
 874    tcg_temp_free_ptr(rd);
 875}
 876
 877static void gen_vpermr(DisasContext *ctx)
 878{
 879    TCGv_ptr ra, rb, rc, rd;
 880    if (unlikely(!ctx->altivec_enabled)) {
 881        gen_exception(ctx, POWERPC_EXCP_VPU);
 882        return;
 883    }
 884    ra = gen_avr_ptr(rA(ctx->opcode));
 885    rb = gen_avr_ptr(rB(ctx->opcode));
 886    rc = gen_avr_ptr(rC(ctx->opcode));
 887    rd = gen_avr_ptr(rD(ctx->opcode));
 888    gen_helper_vpermr(cpu_env, rd, ra, rb, rc);
 889    tcg_temp_free_ptr(ra);
 890    tcg_temp_free_ptr(rb);
 891    tcg_temp_free_ptr(rc);
 892    tcg_temp_free_ptr(rd);
 893}
 894
 895GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
 896GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
 897GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
 898GEN_VAFORM_PAIRED(vsel, vperm, 21)
 899GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
 900
 901GEN_VXFORM_NOA(vclzb, 1, 28)
 902GEN_VXFORM_NOA(vclzh, 1, 29)
 903GEN_VXFORM_NOA(vclzw, 1, 30)
 904GEN_VXFORM_NOA(vclzd, 1, 31)
 905GEN_VXFORM_NOA_2(vnegw, 1, 24, 6)
 906GEN_VXFORM_NOA_2(vnegd, 1, 24, 7)
 907GEN_VXFORM_NOA_2(vextsb2w, 1, 24, 16)
 908GEN_VXFORM_NOA_2(vextsh2w, 1, 24, 17)
 909GEN_VXFORM_NOA_2(vextsb2d, 1, 24, 24)
 910GEN_VXFORM_NOA_2(vextsh2d, 1, 24, 25)
 911GEN_VXFORM_NOA_2(vextsw2d, 1, 24, 26)
 912GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
 913GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
 914GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
 915GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
 916GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
 917GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
 918GEN_VXFORM_NOA(vpopcntb, 1, 28)
 919GEN_VXFORM_NOA(vpopcnth, 1, 29)
 920GEN_VXFORM_NOA(vpopcntw, 1, 30)
 921GEN_VXFORM_NOA(vpopcntd, 1, 31)
 922GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
 923                vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
 924GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
 925                vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
 926GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
 927                vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
 928GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
 929                vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
 930GEN_VXFORM(vbpermd, 6, 23);
 931GEN_VXFORM(vbpermq, 6, 21);
 932GEN_VXFORM_NOA(vgbbd, 6, 20);
 933GEN_VXFORM(vpmsumb, 4, 16)
 934GEN_VXFORM(vpmsumh, 4, 17)
 935GEN_VXFORM(vpmsumw, 4, 18)
 936GEN_VXFORM(vpmsumd, 4, 19)
 937
 938#define GEN_BCD(op)                                 \
 939static void gen_##op(DisasContext *ctx)             \
 940{                                                   \
 941    TCGv_ptr ra, rb, rd;                            \
 942    TCGv_i32 ps;                                    \
 943                                                    \
 944    if (unlikely(!ctx->altivec_enabled)) {          \
 945        gen_exception(ctx, POWERPC_EXCP_VPU);       \
 946        return;                                     \
 947    }                                               \
 948                                                    \
 949    ra = gen_avr_ptr(rA(ctx->opcode));              \
 950    rb = gen_avr_ptr(rB(ctx->opcode));              \
 951    rd = gen_avr_ptr(rD(ctx->opcode));              \
 952                                                    \
 953    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
 954                                                    \
 955    gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
 956                                                    \
 957    tcg_temp_free_ptr(ra);                          \
 958    tcg_temp_free_ptr(rb);                          \
 959    tcg_temp_free_ptr(rd);                          \
 960    tcg_temp_free_i32(ps);                          \
 961}
 962
 963#define GEN_BCD2(op)                                \
 964static void gen_##op(DisasContext *ctx)             \
 965{                                                   \
 966    TCGv_ptr rd, rb;                                \
 967    TCGv_i32 ps;                                    \
 968                                                    \
 969    if (unlikely(!ctx->altivec_enabled)) {          \
 970        gen_exception(ctx, POWERPC_EXCP_VPU);       \
 971        return;                                     \
 972    }                                               \
 973                                                    \
 974    rb = gen_avr_ptr(rB(ctx->opcode));              \
 975    rd = gen_avr_ptr(rD(ctx->opcode));              \
 976                                                    \
 977    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
 978                                                    \
 979    gen_helper_##op(cpu_crf[6], rd, rb, ps);        \
 980                                                    \
 981    tcg_temp_free_ptr(rb);                          \
 982    tcg_temp_free_ptr(rd);                          \
 983    tcg_temp_free_i32(ps);                          \
 984}
 985
 986GEN_BCD(bcdadd)
 987GEN_BCD(bcdsub)
 988GEN_BCD2(bcdcfn)
 989GEN_BCD2(bcdctn)
 990GEN_BCD2(bcdcfz)
 991GEN_BCD2(bcdctz)
 992
 993static void gen_xpnd04_1(DisasContext *ctx)
 994{
 995    switch (opc4(ctx->opcode)) {
 996    case 4:
 997        gen_bcdctz(ctx);
 998        break;
 999    case 5:
1000        gen_bcdctn(ctx);
1001        break;
1002    case 6:
1003        gen_bcdcfz(ctx);
1004        break;
1005    case 7:
1006        gen_bcdcfn(ctx);
1007        break;
1008    default:
1009        gen_invalid(ctx);
1010        break;
1011    }
1012}
1013
1014static void gen_xpnd04_2(DisasContext *ctx)
1015{
1016    switch (opc4(ctx->opcode)) {
1017    case 4:
1018        gen_bcdctz(ctx);
1019        break;
1020    case 6:
1021        gen_bcdcfz(ctx);
1022        break;
1023    case 7:
1024        gen_bcdcfn(ctx);
1025        break;
1026    default:
1027        gen_invalid(ctx);
1028        break;
1029    }
1030}
1031
1032GEN_VXFORM_DUAL(vsubcuw, PPC_ALTIVEC, PPC_NONE, \
1033                xpnd04_1, PPC_NONE, PPC2_ISA300)
1034GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \
1035                xpnd04_2, PPC_NONE, PPC2_ISA300)
1036
1037GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
1038                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
1039GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
1040                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
1041GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
1042                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
1043GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
1044                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
1045
1046static void gen_vsbox(DisasContext *ctx)
1047{
1048    TCGv_ptr ra, rd;
1049    if (unlikely(!ctx->altivec_enabled)) {
1050        gen_exception(ctx, POWERPC_EXCP_VPU);
1051        return;
1052    }
1053    ra = gen_avr_ptr(rA(ctx->opcode));
1054    rd = gen_avr_ptr(rD(ctx->opcode));
1055    gen_helper_vsbox(rd, ra);
1056    tcg_temp_free_ptr(ra);
1057    tcg_temp_free_ptr(rd);
1058}
1059
1060GEN_VXFORM(vcipher, 4, 20)
1061GEN_VXFORM(vcipherlast, 4, 20)
1062GEN_VXFORM(vncipher, 4, 21)
1063GEN_VXFORM(vncipherlast, 4, 21)
1064
1065GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
1066                vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
1067GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
1068                vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
1069
1070#define VSHASIGMA(op)                         \
1071static void gen_##op(DisasContext *ctx)       \
1072{                                             \
1073    TCGv_ptr ra, rd;                          \
1074    TCGv_i32 st_six;                          \
1075    if (unlikely(!ctx->altivec_enabled)) {    \
1076        gen_exception(ctx, POWERPC_EXCP_VPU); \
1077        return;                               \
1078    }                                         \
1079    ra = gen_avr_ptr(rA(ctx->opcode));        \
1080    rd = gen_avr_ptr(rD(ctx->opcode));        \
1081    st_six = tcg_const_i32(rB(ctx->opcode));  \
1082    gen_helper_##op(rd, ra, st_six);          \
1083    tcg_temp_free_ptr(ra);                    \
1084    tcg_temp_free_ptr(rd);                    \
1085    tcg_temp_free_i32(st_six);                \
1086}
1087
1088VSHASIGMA(vshasigmaw)
1089VSHASIGMA(vshasigmad)
1090
1091GEN_VXFORM3(vpermxor, 22, 0xFF)
1092GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
1093                vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
1094
1095#undef GEN_VR_LDX
1096#undef GEN_VR_STX
1097#undef GEN_VR_LVE
1098#undef GEN_VR_STVE
1099
1100#undef GEN_VX_LOGICAL
1101#undef GEN_VX_LOGICAL_207
1102#undef GEN_VXFORM
1103#undef GEN_VXFORM_207
1104#undef GEN_VXFORM_DUAL
1105#undef GEN_VXRFORM_DUAL
1106#undef GEN_VXRFORM1
1107#undef GEN_VXRFORM
1108#undef GEN_VXFORM_SIMM
1109#undef GEN_VXFORM_NOA
1110#undef GEN_VXFORM_UIMM
1111#undef GEN_VAFORM_PAIRED
1112
1113#undef GEN_BCD2
1114