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
 343#define GEN_VXFORM_HETRO(name, opc2, opc3)                              \
 344static void glue(gen_, name)(DisasContext *ctx)                         \
 345{                                                                       \
 346    TCGv_ptr rb;                                                        \
 347    if (unlikely(!ctx->altivec_enabled)) {                              \
 348        gen_exception(ctx, POWERPC_EXCP_VPU);                           \
 349        return;                                                         \
 350    }                                                                   \
 351    rb = gen_avr_ptr(rB(ctx->opcode));                                  \
 352    gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], rb); \
 353    tcg_temp_free_ptr(rb);                                              \
 354}
 355
 356GEN_VXFORM(vaddubm, 0, 0);
 357GEN_VXFORM_DUAL_EXT(vaddubm, PPC_ALTIVEC, PPC_NONE, 0,       \
 358                    vmul10cuq, PPC_NONE, PPC2_ISA300, 0x0000F800)
 359GEN_VXFORM(vadduhm, 0, 1);
 360GEN_VXFORM_DUAL(vadduhm, PPC_ALTIVEC, PPC_NONE,  \
 361                vmul10ecuq, PPC_NONE, PPC2_ISA300)
 362GEN_VXFORM(vadduwm, 0, 2);
 363GEN_VXFORM(vaddudm, 0, 3);
 364GEN_VXFORM(vsububm, 0, 16);
 365GEN_VXFORM(vsubuhm, 0, 17);
 366GEN_VXFORM(vsubuwm, 0, 18);
 367GEN_VXFORM(vsubudm, 0, 19);
 368GEN_VXFORM(vmaxub, 1, 0);
 369GEN_VXFORM(vmaxuh, 1, 1);
 370GEN_VXFORM(vmaxuw, 1, 2);
 371GEN_VXFORM(vmaxud, 1, 3);
 372GEN_VXFORM(vmaxsb, 1, 4);
 373GEN_VXFORM(vmaxsh, 1, 5);
 374GEN_VXFORM(vmaxsw, 1, 6);
 375GEN_VXFORM(vmaxsd, 1, 7);
 376GEN_VXFORM(vminub, 1, 8);
 377GEN_VXFORM(vminuh, 1, 9);
 378GEN_VXFORM(vminuw, 1, 10);
 379GEN_VXFORM(vminud, 1, 11);
 380GEN_VXFORM(vminsb, 1, 12);
 381GEN_VXFORM(vminsh, 1, 13);
 382GEN_VXFORM(vminsw, 1, 14);
 383GEN_VXFORM(vminsd, 1, 15);
 384GEN_VXFORM(vavgub, 1, 16);
 385GEN_VXFORM(vabsdub, 1, 16);
 386GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
 387                vabsdub, PPC_NONE, PPC2_ISA300)
 388GEN_VXFORM(vavguh, 1, 17);
 389GEN_VXFORM(vabsduh, 1, 17);
 390GEN_VXFORM_DUAL(vavguh, PPC_ALTIVEC, PPC_NONE, \
 391                vabsduh, PPC_NONE, PPC2_ISA300)
 392GEN_VXFORM(vavguw, 1, 18);
 393GEN_VXFORM(vabsduw, 1, 18);
 394GEN_VXFORM_DUAL(vavguw, PPC_ALTIVEC, PPC_NONE, \
 395                vabsduw, PPC_NONE, PPC2_ISA300)
 396GEN_VXFORM(vavgsb, 1, 20);
 397GEN_VXFORM(vavgsh, 1, 21);
 398GEN_VXFORM(vavgsw, 1, 22);
 399GEN_VXFORM(vmrghb, 6, 0);
 400GEN_VXFORM(vmrghh, 6, 1);
 401GEN_VXFORM(vmrghw, 6, 2);
 402GEN_VXFORM(vmrglb, 6, 4);
 403GEN_VXFORM(vmrglh, 6, 5);
 404GEN_VXFORM(vmrglw, 6, 6);
 405
 406static void gen_vmrgew(DisasContext *ctx)
 407{
 408    TCGv_i64 tmp;
 409    int VT, VA, VB;
 410    if (unlikely(!ctx->altivec_enabled)) {
 411        gen_exception(ctx, POWERPC_EXCP_VPU);
 412        return;
 413    }
 414    VT = rD(ctx->opcode);
 415    VA = rA(ctx->opcode);
 416    VB = rB(ctx->opcode);
 417    tmp = tcg_temp_new_i64();
 418    tcg_gen_shri_i64(tmp, cpu_avrh[VB], 32);
 419    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VA], tmp, 0, 32);
 420    tcg_gen_shri_i64(tmp, cpu_avrl[VB], 32);
 421    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VA], tmp, 0, 32);
 422    tcg_temp_free_i64(tmp);
 423}
 424
 425static void gen_vmrgow(DisasContext *ctx)
 426{
 427    int VT, VA, VB;
 428    if (unlikely(!ctx->altivec_enabled)) {
 429        gen_exception(ctx, POWERPC_EXCP_VPU);
 430        return;
 431    }
 432    VT = rD(ctx->opcode);
 433    VA = rA(ctx->opcode);
 434    VB = rB(ctx->opcode);
 435
 436    tcg_gen_deposit_i64(cpu_avrh[VT], cpu_avrh[VB], cpu_avrh[VA], 32, 32);
 437    tcg_gen_deposit_i64(cpu_avrl[VT], cpu_avrl[VB], cpu_avrl[VA], 32, 32);
 438}
 439
 440GEN_VXFORM(vmuloub, 4, 0);
 441GEN_VXFORM(vmulouh, 4, 1);
 442GEN_VXFORM(vmulouw, 4, 2);
 443GEN_VXFORM(vmuluwm, 4, 2);
 444GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
 445                vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
 446GEN_VXFORM(vmulosb, 4, 4);
 447GEN_VXFORM(vmulosh, 4, 5);
 448GEN_VXFORM(vmulosw, 4, 6);
 449GEN_VXFORM(vmuleub, 4, 8);
 450GEN_VXFORM(vmuleuh, 4, 9);
 451GEN_VXFORM(vmuleuw, 4, 10);
 452GEN_VXFORM(vmulesb, 4, 12);
 453GEN_VXFORM(vmulesh, 4, 13);
 454GEN_VXFORM(vmulesw, 4, 14);
 455GEN_VXFORM(vslb, 2, 4);
 456GEN_VXFORM(vslh, 2, 5);
 457GEN_VXFORM(vslw, 2, 6);
 458GEN_VXFORM(vrlwnm, 2, 6);
 459GEN_VXFORM_DUAL(vslw, PPC_ALTIVEC, PPC_NONE, \
 460                vrlwnm, PPC_NONE, PPC2_ISA300)
 461GEN_VXFORM(vsld, 2, 23);
 462GEN_VXFORM(vsrb, 2, 8);
 463GEN_VXFORM(vsrh, 2, 9);
 464GEN_VXFORM(vsrw, 2, 10);
 465GEN_VXFORM(vsrd, 2, 27);
 466GEN_VXFORM(vsrab, 2, 12);
 467GEN_VXFORM(vsrah, 2, 13);
 468GEN_VXFORM(vsraw, 2, 14);
 469GEN_VXFORM(vsrad, 2, 15);
 470GEN_VXFORM(vsrv, 2, 28);
 471GEN_VXFORM(vslv, 2, 29);
 472GEN_VXFORM(vslo, 6, 16);
 473GEN_VXFORM(vsro, 6, 17);
 474GEN_VXFORM(vaddcuw, 0, 6);
 475GEN_VXFORM(vsubcuw, 0, 22);
 476GEN_VXFORM_ENV(vaddubs, 0, 8);
 477GEN_VXFORM_DUAL_EXT(vaddubs, PPC_ALTIVEC, PPC_NONE, 0,       \
 478                    vmul10uq, PPC_NONE, PPC2_ISA300, 0x0000F800)
 479GEN_VXFORM_ENV(vadduhs, 0, 9);
 480GEN_VXFORM_DUAL(vadduhs, PPC_ALTIVEC, PPC_NONE, \
 481                vmul10euq, PPC_NONE, PPC2_ISA300)
 482GEN_VXFORM_ENV(vadduws, 0, 10);
 483GEN_VXFORM_ENV(vaddsbs, 0, 12);
 484GEN_VXFORM_ENV(vaddshs, 0, 13);
 485GEN_VXFORM_ENV(vaddsws, 0, 14);
 486GEN_VXFORM_ENV(vsububs, 0, 24);
 487GEN_VXFORM_ENV(vsubuhs, 0, 25);
 488GEN_VXFORM_ENV(vsubuws, 0, 26);
 489GEN_VXFORM_ENV(vsubsbs, 0, 28);
 490GEN_VXFORM_ENV(vsubshs, 0, 29);
 491GEN_VXFORM_ENV(vsubsws, 0, 30);
 492GEN_VXFORM(vadduqm, 0, 4);
 493GEN_VXFORM(vaddcuq, 0, 5);
 494GEN_VXFORM3(vaddeuqm, 30, 0);
 495GEN_VXFORM3(vaddecuq, 30, 0);
 496GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
 497            vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
 498GEN_VXFORM(vsubuqm, 0, 20);
 499GEN_VXFORM(vsubcuq, 0, 21);
 500GEN_VXFORM3(vsubeuqm, 31, 0);
 501GEN_VXFORM3(vsubecuq, 31, 0);
 502GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
 503            vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
 504GEN_VXFORM(vrlb, 2, 0);
 505GEN_VXFORM(vrlh, 2, 1);
 506GEN_VXFORM(vrlw, 2, 2);
 507GEN_VXFORM(vrlwmi, 2, 2);
 508GEN_VXFORM_DUAL(vrlw, PPC_ALTIVEC, PPC_NONE, \
 509                vrlwmi, PPC_NONE, PPC2_ISA300)
 510GEN_VXFORM(vrld, 2, 3);
 511GEN_VXFORM(vrldmi, 2, 3);
 512GEN_VXFORM_DUAL(vrld, PPC_NONE, PPC2_ALTIVEC_207, \
 513                vrldmi, PPC_NONE, PPC2_ISA300)
 514GEN_VXFORM(vsl, 2, 7);
 515GEN_VXFORM(vrldnm, 2, 7);
 516GEN_VXFORM_DUAL(vsl, PPC_ALTIVEC, PPC_NONE, \
 517                vrldnm, PPC_NONE, PPC2_ISA300)
 518GEN_VXFORM(vsr, 2, 11);
 519GEN_VXFORM_ENV(vpkuhum, 7, 0);
 520GEN_VXFORM_ENV(vpkuwum, 7, 1);
 521GEN_VXFORM_ENV(vpkudum, 7, 17);
 522GEN_VXFORM_ENV(vpkuhus, 7, 2);
 523GEN_VXFORM_ENV(vpkuwus, 7, 3);
 524GEN_VXFORM_ENV(vpkudus, 7, 19);
 525GEN_VXFORM_ENV(vpkshus, 7, 4);
 526GEN_VXFORM_ENV(vpkswus, 7, 5);
 527GEN_VXFORM_ENV(vpksdus, 7, 21);
 528GEN_VXFORM_ENV(vpkshss, 7, 6);
 529GEN_VXFORM_ENV(vpkswss, 7, 7);
 530GEN_VXFORM_ENV(vpksdss, 7, 23);
 531GEN_VXFORM(vpkpx, 7, 12);
 532GEN_VXFORM_ENV(vsum4ubs, 4, 24);
 533GEN_VXFORM_ENV(vsum4sbs, 4, 28);
 534GEN_VXFORM_ENV(vsum4shs, 4, 25);
 535GEN_VXFORM_ENV(vsum2sws, 4, 26);
 536GEN_VXFORM_ENV(vsumsws, 4, 30);
 537GEN_VXFORM_ENV(vaddfp, 5, 0);
 538GEN_VXFORM_ENV(vsubfp, 5, 1);
 539GEN_VXFORM_ENV(vmaxfp, 5, 16);
 540GEN_VXFORM_ENV(vminfp, 5, 17);
 541GEN_VXFORM_HETRO(vextublx, 6, 24)
 542GEN_VXFORM_HETRO(vextuhlx, 6, 25)
 543GEN_VXFORM_HETRO(vextuwlx, 6, 26)
 544GEN_VXFORM_DUAL(vmrgow, PPC_NONE, PPC2_ALTIVEC_207,
 545                vextuwlx, PPC_NONE, PPC2_ISA300)
 546GEN_VXFORM_HETRO(vextubrx, 6, 28)
 547GEN_VXFORM_HETRO(vextuhrx, 6, 29)
 548GEN_VXFORM_HETRO(vextuwrx, 6, 30)
 549GEN_VXFORM_DUAL(vmrgew, PPC_NONE, PPC2_ALTIVEC_207, \
 550                vextuwrx, PPC_NONE, PPC2_ISA300)
 551
 552#define GEN_VXRFORM1(opname, name, str, opc2, opc3)                     \
 553static void glue(gen_, name)(DisasContext *ctx)                         \
 554    {                                                                   \
 555        TCGv_ptr ra, rb, rd;                                            \
 556        if (unlikely(!ctx->altivec_enabled)) {                          \
 557            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 558            return;                                                     \
 559        }                                                               \
 560        ra = gen_avr_ptr(rA(ctx->opcode));                              \
 561        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 562        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 563        gen_helper_##opname(cpu_env, rd, ra, rb);                       \
 564        tcg_temp_free_ptr(ra);                                          \
 565        tcg_temp_free_ptr(rb);                                          \
 566        tcg_temp_free_ptr(rd);                                          \
 567    }
 568
 569#define GEN_VXRFORM(name, opc2, opc3)                                \
 570    GEN_VXRFORM1(name, name, #name, opc2, opc3)                      \
 571    GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
 572
 573/*
 574 * Support for Altivec instructions that use bit 31 (Rc) as an opcode
 575 * bit but also use bit 21 as an actual Rc bit.  In general, thse pairs
 576 * come from different versions of the ISA, so we must also support a
 577 * pair of flags for each instruction.
 578 */
 579#define GEN_VXRFORM_DUAL(name0, flg0, flg2_0, name1, flg1, flg2_1)     \
 580static void glue(gen_, name0##_##name1)(DisasContext *ctx)             \
 581{                                                                      \
 582    if ((Rc(ctx->opcode) == 0) &&                                      \
 583        ((ctx->insns_flags & flg0) || (ctx->insns_flags2 & flg2_0))) { \
 584        if (Rc21(ctx->opcode) == 0) {                                  \
 585            gen_##name0(ctx);                                          \
 586        } else {                                                       \
 587            gen_##name0##_(ctx);                                       \
 588        }                                                              \
 589    } else if ((Rc(ctx->opcode) == 1) &&                               \
 590        ((ctx->insns_flags & flg1) || (ctx->insns_flags2 & flg2_1))) { \
 591        if (Rc21(ctx->opcode) == 0) {                                  \
 592            gen_##name1(ctx);                                          \
 593        } else {                                                       \
 594            gen_##name1##_(ctx);                                       \
 595        }                                                              \
 596    } else {                                                           \
 597        gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);            \
 598    }                                                                  \
 599}
 600
 601GEN_VXRFORM(vcmpequb, 3, 0)
 602GEN_VXRFORM(vcmpequh, 3, 1)
 603GEN_VXRFORM(vcmpequw, 3, 2)
 604GEN_VXRFORM(vcmpequd, 3, 3)
 605GEN_VXRFORM(vcmpnezb, 3, 4)
 606GEN_VXRFORM(vcmpnezh, 3, 5)
 607GEN_VXRFORM(vcmpnezw, 3, 6)
 608GEN_VXRFORM(vcmpgtsb, 3, 12)
 609GEN_VXRFORM(vcmpgtsh, 3, 13)
 610GEN_VXRFORM(vcmpgtsw, 3, 14)
 611GEN_VXRFORM(vcmpgtsd, 3, 15)
 612GEN_VXRFORM(vcmpgtub, 3, 8)
 613GEN_VXRFORM(vcmpgtuh, 3, 9)
 614GEN_VXRFORM(vcmpgtuw, 3, 10)
 615GEN_VXRFORM(vcmpgtud, 3, 11)
 616GEN_VXRFORM(vcmpeqfp, 3, 3)
 617GEN_VXRFORM(vcmpgefp, 3, 7)
 618GEN_VXRFORM(vcmpgtfp, 3, 11)
 619GEN_VXRFORM(vcmpbfp, 3, 15)
 620GEN_VXRFORM(vcmpneb, 3, 0)
 621GEN_VXRFORM(vcmpneh, 3, 1)
 622GEN_VXRFORM(vcmpnew, 3, 2)
 623
 624GEN_VXRFORM_DUAL(vcmpequb, PPC_ALTIVEC, PPC_NONE, \
 625                 vcmpneb, PPC_NONE, PPC2_ISA300)
 626GEN_VXRFORM_DUAL(vcmpequh, PPC_ALTIVEC, PPC_NONE, \
 627                 vcmpneh, PPC_NONE, PPC2_ISA300)
 628GEN_VXRFORM_DUAL(vcmpequw, PPC_ALTIVEC, PPC_NONE, \
 629                 vcmpnew, PPC_NONE, PPC2_ISA300)
 630GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
 631                 vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
 632GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
 633                 vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
 634GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
 635                 vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
 636
 637#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
 638static void glue(gen_, name)(DisasContext *ctx)                         \
 639    {                                                                   \
 640        TCGv_ptr rd;                                                    \
 641        TCGv_i32 simm;                                                  \
 642        if (unlikely(!ctx->altivec_enabled)) {                          \
 643            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 644            return;                                                     \
 645        }                                                               \
 646        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
 647        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 648        gen_helper_##name (rd, simm);                                   \
 649        tcg_temp_free_i32(simm);                                        \
 650        tcg_temp_free_ptr(rd);                                          \
 651    }
 652
 653GEN_VXFORM_SIMM(vspltisb, 6, 12);
 654GEN_VXFORM_SIMM(vspltish, 6, 13);
 655GEN_VXFORM_SIMM(vspltisw, 6, 14);
 656
 657#define GEN_VXFORM_NOA(name, opc2, opc3)                                \
 658static void glue(gen_, name)(DisasContext *ctx)                                 \
 659    {                                                                   \
 660        TCGv_ptr rb, rd;                                                \
 661        if (unlikely(!ctx->altivec_enabled)) {                          \
 662            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 663            return;                                                     \
 664        }                                                               \
 665        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 666        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 667        gen_helper_##name (rd, rb);                                     \
 668        tcg_temp_free_ptr(rb);                                          \
 669        tcg_temp_free_ptr(rd);                                         \
 670    }
 671
 672#define GEN_VXFORM_NOA_ENV(name, opc2, opc3)                            \
 673static void glue(gen_, name)(DisasContext *ctx)                         \
 674    {                                                                   \
 675        TCGv_ptr rb, rd;                                                \
 676                                                                        \
 677        if (unlikely(!ctx->altivec_enabled)) {                          \
 678            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 679            return;                                                     \
 680        }                                                               \
 681        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 682        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 683        gen_helper_##name(cpu_env, rd, rb);                             \
 684        tcg_temp_free_ptr(rb);                                          \
 685        tcg_temp_free_ptr(rd);                                          \
 686    }
 687
 688#define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4)                        \
 689static void glue(gen_, name)(DisasContext *ctx)                         \
 690    {                                                                   \
 691        TCGv_ptr rb, rd;                                                \
 692        if (unlikely(!ctx->altivec_enabled)) {                          \
 693            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 694            return;                                                     \
 695        }                                                               \
 696        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 697        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 698        gen_helper_##name(rd, rb);                                      \
 699        tcg_temp_free_ptr(rb);                                          \
 700        tcg_temp_free_ptr(rd);                                          \
 701    }
 702
 703#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4)                        \
 704static void glue(gen_, name)(DisasContext *ctx)                         \
 705    {                                                                   \
 706        TCGv_ptr rb;                                                    \
 707        if (unlikely(!ctx->altivec_enabled)) {                          \
 708            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 709            return;                                                     \
 710        }                                                               \
 711        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 712        gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb);                \
 713        tcg_temp_free_ptr(rb);                                          \
 714    }
 715GEN_VXFORM_NOA(vupkhsb, 7, 8);
 716GEN_VXFORM_NOA(vupkhsh, 7, 9);
 717GEN_VXFORM_NOA(vupkhsw, 7, 25);
 718GEN_VXFORM_NOA(vupklsb, 7, 10);
 719GEN_VXFORM_NOA(vupklsh, 7, 11);
 720GEN_VXFORM_NOA(vupklsw, 7, 27);
 721GEN_VXFORM_NOA(vupkhpx, 7, 13);
 722GEN_VXFORM_NOA(vupklpx, 7, 15);
 723GEN_VXFORM_NOA_ENV(vrefp, 5, 4);
 724GEN_VXFORM_NOA_ENV(vrsqrtefp, 5, 5);
 725GEN_VXFORM_NOA_ENV(vexptefp, 5, 6);
 726GEN_VXFORM_NOA_ENV(vlogefp, 5, 7);
 727GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
 728GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
 729GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
 730GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
 731GEN_VXFORM_NOA(vprtybw, 1, 24);
 732GEN_VXFORM_NOA(vprtybd, 1, 24);
 733GEN_VXFORM_NOA(vprtybq, 1, 24);
 734
 735#define GEN_VXFORM_SIMM(name, opc2, opc3)                               \
 736static void glue(gen_, name)(DisasContext *ctx)                                 \
 737    {                                                                   \
 738        TCGv_ptr rd;                                                    \
 739        TCGv_i32 simm;                                                  \
 740        if (unlikely(!ctx->altivec_enabled)) {                          \
 741            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 742            return;                                                     \
 743        }                                                               \
 744        simm = tcg_const_i32(SIMM5(ctx->opcode));                       \
 745        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 746        gen_helper_##name (rd, simm);                                   \
 747        tcg_temp_free_i32(simm);                                        \
 748        tcg_temp_free_ptr(rd);                                          \
 749    }
 750
 751#define GEN_VXFORM_UIMM(name, opc2, opc3)                               \
 752static void glue(gen_, name)(DisasContext *ctx)                                 \
 753    {                                                                   \
 754        TCGv_ptr rb, rd;                                                \
 755        TCGv_i32 uimm;                                                  \
 756        if (unlikely(!ctx->altivec_enabled)) {                          \
 757            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 758            return;                                                     \
 759        }                                                               \
 760        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
 761        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 762        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 763        gen_helper_##name (rd, rb, uimm);                               \
 764        tcg_temp_free_i32(uimm);                                        \
 765        tcg_temp_free_ptr(rb);                                          \
 766        tcg_temp_free_ptr(rd);                                          \
 767    }
 768
 769#define GEN_VXFORM_UIMM_ENV(name, opc2, opc3)                           \
 770static void glue(gen_, name)(DisasContext *ctx)                         \
 771    {                                                                   \
 772        TCGv_ptr rb, rd;                                                \
 773        TCGv_i32 uimm;                                                  \
 774                                                                        \
 775        if (unlikely(!ctx->altivec_enabled)) {                          \
 776            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 777            return;                                                     \
 778        }                                                               \
 779        uimm = tcg_const_i32(UIMM5(ctx->opcode));                       \
 780        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 781        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 782        gen_helper_##name(cpu_env, rd, rb, uimm);                       \
 783        tcg_temp_free_i32(uimm);                                        \
 784        tcg_temp_free_ptr(rb);                                          \
 785        tcg_temp_free_ptr(rd);                                          \
 786    }
 787
 788#define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max)              \
 789static void glue(gen_, name)(DisasContext *ctx)                         \
 790    {                                                                   \
 791        TCGv_ptr rb, rd;                                                \
 792        uint8_t uimm = UIMM4(ctx->opcode);                              \
 793        TCGv_i32 t0 = tcg_temp_new_i32();                               \
 794        if (unlikely(!ctx->altivec_enabled)) {                          \
 795            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 796            return;                                                     \
 797        }                                                               \
 798        if (uimm > splat_max) {                                         \
 799            uimm = 0;                                                   \
 800        }                                                               \
 801        tcg_gen_movi_i32(t0, uimm);                                     \
 802        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 803        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 804        gen_helper_##name(rd, rb, t0);                                  \
 805        tcg_temp_free_i32(t0);                                          \
 806        tcg_temp_free_ptr(rb);                                          \
 807        tcg_temp_free_ptr(rd);                                          \
 808    }
 809
 810GEN_VXFORM_UIMM(vspltb, 6, 8);
 811GEN_VXFORM_UIMM(vsplth, 6, 9);
 812GEN_VXFORM_UIMM(vspltw, 6, 10);
 813GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
 814GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
 815GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
 816GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
 817GEN_VXFORM_UIMM_SPLAT(vinsertb, 6, 12, 15);
 818GEN_VXFORM_UIMM_SPLAT(vinserth, 6, 13, 14);
 819GEN_VXFORM_UIMM_SPLAT(vinsertw, 6, 14, 12);
 820GEN_VXFORM_UIMM_SPLAT(vinsertd, 6, 15, 8);
 821GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
 822GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
 823GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
 824GEN_VXFORM_UIMM_ENV(vctsxs, 5, 15);
 825GEN_VXFORM_DUAL(vspltb, PPC_ALTIVEC, PPC_NONE,
 826                vextractub, PPC_NONE, PPC2_ISA300);
 827GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
 828                vextractuh, PPC_NONE, PPC2_ISA300);
 829GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
 830                vextractuw, PPC_NONE, PPC2_ISA300);
 831GEN_VXFORM_DUAL(vspltisb, PPC_ALTIVEC, PPC_NONE,
 832                vinsertb, PPC_NONE, PPC2_ISA300);
 833GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
 834                vinserth, PPC_NONE, PPC2_ISA300);
 835GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
 836                vinsertw, PPC_NONE, PPC2_ISA300);
 837
 838static void gen_vsldoi(DisasContext *ctx)
 839{
 840    TCGv_ptr ra, rb, rd;
 841    TCGv_i32 sh;
 842    if (unlikely(!ctx->altivec_enabled)) {
 843        gen_exception(ctx, POWERPC_EXCP_VPU);
 844        return;
 845    }
 846    ra = gen_avr_ptr(rA(ctx->opcode));
 847    rb = gen_avr_ptr(rB(ctx->opcode));
 848    rd = gen_avr_ptr(rD(ctx->opcode));
 849    sh = tcg_const_i32(VSH(ctx->opcode));
 850    gen_helper_vsldoi (rd, ra, rb, sh);
 851    tcg_temp_free_ptr(ra);
 852    tcg_temp_free_ptr(rb);
 853    tcg_temp_free_ptr(rd);
 854    tcg_temp_free_i32(sh);
 855}
 856
 857#define GEN_VAFORM_PAIRED(name0, name1, opc2)                           \
 858static void glue(gen_, name0##_##name1)(DisasContext *ctx)              \
 859    {                                                                   \
 860        TCGv_ptr ra, rb, rc, rd;                                        \
 861        if (unlikely(!ctx->altivec_enabled)) {                          \
 862            gen_exception(ctx, POWERPC_EXCP_VPU);                       \
 863            return;                                                     \
 864        }                                                               \
 865        ra = gen_avr_ptr(rA(ctx->opcode));                              \
 866        rb = gen_avr_ptr(rB(ctx->opcode));                              \
 867        rc = gen_avr_ptr(rC(ctx->opcode));                              \
 868        rd = gen_avr_ptr(rD(ctx->opcode));                              \
 869        if (Rc(ctx->opcode)) {                                          \
 870            gen_helper_##name1(cpu_env, rd, ra, rb, rc);                \
 871        } else {                                                        \
 872            gen_helper_##name0(cpu_env, rd, ra, rb, rc);                \
 873        }                                                               \
 874        tcg_temp_free_ptr(ra);                                          \
 875        tcg_temp_free_ptr(rb);                                          \
 876        tcg_temp_free_ptr(rc);                                          \
 877        tcg_temp_free_ptr(rd);                                          \
 878    }
 879
 880GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
 881
 882static void gen_vmladduhm(DisasContext *ctx)
 883{
 884    TCGv_ptr ra, rb, rc, rd;
 885    if (unlikely(!ctx->altivec_enabled)) {
 886        gen_exception(ctx, POWERPC_EXCP_VPU);
 887        return;
 888    }
 889    ra = gen_avr_ptr(rA(ctx->opcode));
 890    rb = gen_avr_ptr(rB(ctx->opcode));
 891    rc = gen_avr_ptr(rC(ctx->opcode));
 892    rd = gen_avr_ptr(rD(ctx->opcode));
 893    gen_helper_vmladduhm(rd, ra, rb, rc);
 894    tcg_temp_free_ptr(ra);
 895    tcg_temp_free_ptr(rb);
 896    tcg_temp_free_ptr(rc);
 897    tcg_temp_free_ptr(rd);
 898}
 899
 900static void gen_vpermr(DisasContext *ctx)
 901{
 902    TCGv_ptr ra, rb, rc, rd;
 903    if (unlikely(!ctx->altivec_enabled)) {
 904        gen_exception(ctx, POWERPC_EXCP_VPU);
 905        return;
 906    }
 907    ra = gen_avr_ptr(rA(ctx->opcode));
 908    rb = gen_avr_ptr(rB(ctx->opcode));
 909    rc = gen_avr_ptr(rC(ctx->opcode));
 910    rd = gen_avr_ptr(rD(ctx->opcode));
 911    gen_helper_vpermr(cpu_env, rd, ra, rb, rc);
 912    tcg_temp_free_ptr(ra);
 913    tcg_temp_free_ptr(rb);
 914    tcg_temp_free_ptr(rc);
 915    tcg_temp_free_ptr(rd);
 916}
 917
 918GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
 919GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
 920GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
 921GEN_VAFORM_PAIRED(vsel, vperm, 21)
 922GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
 923
 924GEN_VXFORM_NOA(vclzb, 1, 28)
 925GEN_VXFORM_NOA(vclzh, 1, 29)
 926GEN_VXFORM_NOA(vclzw, 1, 30)
 927GEN_VXFORM_NOA(vclzd, 1, 31)
 928GEN_VXFORM_NOA_2(vnegw, 1, 24, 6)
 929GEN_VXFORM_NOA_2(vnegd, 1, 24, 7)
 930GEN_VXFORM_NOA_2(vextsb2w, 1, 24, 16)
 931GEN_VXFORM_NOA_2(vextsh2w, 1, 24, 17)
 932GEN_VXFORM_NOA_2(vextsb2d, 1, 24, 24)
 933GEN_VXFORM_NOA_2(vextsh2d, 1, 24, 25)
 934GEN_VXFORM_NOA_2(vextsw2d, 1, 24, 26)
 935GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
 936GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
 937GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
 938GEN_VXFORM_NOA_2(vctzd, 1, 24, 31)
 939GEN_VXFORM_NOA_3(vclzlsbb, 1, 24, 0)
 940GEN_VXFORM_NOA_3(vctzlsbb, 1, 24, 1)
 941GEN_VXFORM_NOA(vpopcntb, 1, 28)
 942GEN_VXFORM_NOA(vpopcnth, 1, 29)
 943GEN_VXFORM_NOA(vpopcntw, 1, 30)
 944GEN_VXFORM_NOA(vpopcntd, 1, 31)
 945GEN_VXFORM_DUAL(vclzb, PPC_NONE, PPC2_ALTIVEC_207, \
 946                vpopcntb, PPC_NONE, PPC2_ALTIVEC_207)
 947GEN_VXFORM_DUAL(vclzh, PPC_NONE, PPC2_ALTIVEC_207, \
 948                vpopcnth, PPC_NONE, PPC2_ALTIVEC_207)
 949GEN_VXFORM_DUAL(vclzw, PPC_NONE, PPC2_ALTIVEC_207, \
 950                vpopcntw, PPC_NONE, PPC2_ALTIVEC_207)
 951GEN_VXFORM_DUAL(vclzd, PPC_NONE, PPC2_ALTIVEC_207, \
 952                vpopcntd, PPC_NONE, PPC2_ALTIVEC_207)
 953GEN_VXFORM(vbpermd, 6, 23);
 954GEN_VXFORM(vbpermq, 6, 21);
 955GEN_VXFORM_NOA(vgbbd, 6, 20);
 956GEN_VXFORM(vpmsumb, 4, 16)
 957GEN_VXFORM(vpmsumh, 4, 17)
 958GEN_VXFORM(vpmsumw, 4, 18)
 959GEN_VXFORM(vpmsumd, 4, 19)
 960
 961#define GEN_BCD(op)                                 \
 962static void gen_##op(DisasContext *ctx)             \
 963{                                                   \
 964    TCGv_ptr ra, rb, rd;                            \
 965    TCGv_i32 ps;                                    \
 966                                                    \
 967    if (unlikely(!ctx->altivec_enabled)) {          \
 968        gen_exception(ctx, POWERPC_EXCP_VPU);       \
 969        return;                                     \
 970    }                                               \
 971                                                    \
 972    ra = gen_avr_ptr(rA(ctx->opcode));              \
 973    rb = gen_avr_ptr(rB(ctx->opcode));              \
 974    rd = gen_avr_ptr(rD(ctx->opcode));              \
 975                                                    \
 976    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
 977                                                    \
 978    gen_helper_##op(cpu_crf[6], rd, ra, rb, ps);    \
 979                                                    \
 980    tcg_temp_free_ptr(ra);                          \
 981    tcg_temp_free_ptr(rb);                          \
 982    tcg_temp_free_ptr(rd);                          \
 983    tcg_temp_free_i32(ps);                          \
 984}
 985
 986#define GEN_BCD2(op)                                \
 987static void gen_##op(DisasContext *ctx)             \
 988{                                                   \
 989    TCGv_ptr rd, rb;                                \
 990    TCGv_i32 ps;                                    \
 991                                                    \
 992    if (unlikely(!ctx->altivec_enabled)) {          \
 993        gen_exception(ctx, POWERPC_EXCP_VPU);       \
 994        return;                                     \
 995    }                                               \
 996                                                    \
 997    rb = gen_avr_ptr(rB(ctx->opcode));              \
 998    rd = gen_avr_ptr(rD(ctx->opcode));              \
 999                                                    \
1000    ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
1001                                                    \
1002    gen_helper_##op(cpu_crf[6], rd, rb, ps);        \
1003                                                    \
1004    tcg_temp_free_ptr(rb);                          \
1005    tcg_temp_free_ptr(rd);                          \
1006    tcg_temp_free_i32(ps);                          \
1007}
1008
1009GEN_BCD(bcdadd)
1010GEN_BCD(bcdsub)
1011GEN_BCD2(bcdcfn)
1012GEN_BCD2(bcdctn)
1013GEN_BCD2(bcdcfz)
1014GEN_BCD2(bcdctz)
1015GEN_BCD2(bcdcfsq)
1016GEN_BCD2(bcdctsq)
1017GEN_BCD2(bcdsetsgn)
1018GEN_BCD(bcdcpsgn);
1019GEN_BCD(bcds);
1020GEN_BCD(bcdus);
1021GEN_BCD(bcdsr);
1022GEN_BCD(bcdtrunc);
1023GEN_BCD(bcdutrunc);
1024
1025static void gen_xpnd04_1(DisasContext *ctx)
1026{
1027    switch (opc4(ctx->opcode)) {
1028    case 0:
1029        gen_bcdctsq(ctx);
1030        break;
1031    case 2:
1032        gen_bcdcfsq(ctx);
1033        break;
1034    case 4:
1035        gen_bcdctz(ctx);
1036        break;
1037    case 5:
1038        gen_bcdctn(ctx);
1039        break;
1040    case 6:
1041        gen_bcdcfz(ctx);
1042        break;
1043    case 7:
1044        gen_bcdcfn(ctx);
1045        break;
1046    case 31:
1047        gen_bcdsetsgn(ctx);
1048        break;
1049    default:
1050        gen_invalid(ctx);
1051        break;
1052    }
1053}
1054
1055static void gen_xpnd04_2(DisasContext *ctx)
1056{
1057    switch (opc4(ctx->opcode)) {
1058    case 0:
1059        gen_bcdctsq(ctx);
1060        break;
1061    case 2:
1062        gen_bcdcfsq(ctx);
1063        break;
1064    case 4:
1065        gen_bcdctz(ctx);
1066        break;
1067    case 6:
1068        gen_bcdcfz(ctx);
1069        break;
1070    case 7:
1071        gen_bcdcfn(ctx);
1072        break;
1073    case 31:
1074        gen_bcdsetsgn(ctx);
1075        break;
1076    default:
1077        gen_invalid(ctx);
1078        break;
1079    }
1080}
1081
1082
1083GEN_VXFORM_DUAL(vsubcuw, PPC_ALTIVEC, PPC_NONE, \
1084                xpnd04_1, PPC_NONE, PPC2_ISA300)
1085GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \
1086                xpnd04_2, PPC_NONE, PPC2_ISA300)
1087
1088GEN_VXFORM_DUAL(vsububm, PPC_ALTIVEC, PPC_NONE, \
1089                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
1090GEN_VXFORM_DUAL(vsububs, PPC_ALTIVEC, PPC_NONE, \
1091                bcdadd, PPC_NONE, PPC2_ALTIVEC_207)
1092GEN_VXFORM_DUAL(vsubuhm, PPC_ALTIVEC, PPC_NONE, \
1093                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
1094GEN_VXFORM_DUAL(vsubuhs, PPC_ALTIVEC, PPC_NONE, \
1095                bcdsub, PPC_NONE, PPC2_ALTIVEC_207)
1096GEN_VXFORM_DUAL(vaddshs, PPC_ALTIVEC, PPC_NONE, \
1097                bcdcpsgn, PPC_NONE, PPC2_ISA300)
1098GEN_VXFORM_DUAL(vsubudm, PPC2_ALTIVEC_207, PPC_NONE, \
1099                bcds, PPC_NONE, PPC2_ISA300)
1100GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
1101                bcdus, PPC_NONE, PPC2_ISA300)
1102GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
1103                bcdtrunc, PPC_NONE, PPC2_ISA300)
1104GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
1105                bcdtrunc, PPC_NONE, PPC2_ISA300)
1106GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
1107                bcdutrunc, PPC_NONE, PPC2_ISA300)
1108
1109
1110static void gen_vsbox(DisasContext *ctx)
1111{
1112    TCGv_ptr ra, rd;
1113    if (unlikely(!ctx->altivec_enabled)) {
1114        gen_exception(ctx, POWERPC_EXCP_VPU);
1115        return;
1116    }
1117    ra = gen_avr_ptr(rA(ctx->opcode));
1118    rd = gen_avr_ptr(rD(ctx->opcode));
1119    gen_helper_vsbox(rd, ra);
1120    tcg_temp_free_ptr(ra);
1121    tcg_temp_free_ptr(rd);
1122}
1123
1124GEN_VXFORM(vcipher, 4, 20)
1125GEN_VXFORM(vcipherlast, 4, 20)
1126GEN_VXFORM(vncipher, 4, 21)
1127GEN_VXFORM(vncipherlast, 4, 21)
1128
1129GEN_VXFORM_DUAL(vcipher, PPC_NONE, PPC2_ALTIVEC_207,
1130                vcipherlast, PPC_NONE, PPC2_ALTIVEC_207)
1131GEN_VXFORM_DUAL(vncipher, PPC_NONE, PPC2_ALTIVEC_207,
1132                vncipherlast, PPC_NONE, PPC2_ALTIVEC_207)
1133
1134#define VSHASIGMA(op)                         \
1135static void gen_##op(DisasContext *ctx)       \
1136{                                             \
1137    TCGv_ptr ra, rd;                          \
1138    TCGv_i32 st_six;                          \
1139    if (unlikely(!ctx->altivec_enabled)) {    \
1140        gen_exception(ctx, POWERPC_EXCP_VPU); \
1141        return;                               \
1142    }                                         \
1143    ra = gen_avr_ptr(rA(ctx->opcode));        \
1144    rd = gen_avr_ptr(rD(ctx->opcode));        \
1145    st_six = tcg_const_i32(rB(ctx->opcode));  \
1146    gen_helper_##op(rd, ra, st_six);          \
1147    tcg_temp_free_ptr(ra);                    \
1148    tcg_temp_free_ptr(rd);                    \
1149    tcg_temp_free_i32(st_six);                \
1150}
1151
1152VSHASIGMA(vshasigmaw)
1153VSHASIGMA(vshasigmad)
1154
1155GEN_VXFORM3(vpermxor, 22, 0xFF)
1156GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
1157                vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
1158
1159#undef GEN_VR_LDX
1160#undef GEN_VR_STX
1161#undef GEN_VR_LVE
1162#undef GEN_VR_STVE
1163
1164#undef GEN_VX_LOGICAL
1165#undef GEN_VX_LOGICAL_207
1166#undef GEN_VXFORM
1167#undef GEN_VXFORM_207
1168#undef GEN_VXFORM_DUAL
1169#undef GEN_VXRFORM_DUAL
1170#undef GEN_VXRFORM1
1171#undef GEN_VXRFORM
1172#undef GEN_VXFORM_SIMM
1173#undef GEN_VXFORM_NOA
1174#undef GEN_VXFORM_UIMM
1175#undef GEN_VAFORM_PAIRED
1176
1177#undef GEN_BCD2
1178