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